自定义函数参数传递问题

wdsimon 2008-04-25 11:01:36
前几天提问解答了自定义函数中不能使用临时表的问题(已加分结贴):
http://topic.csdn.net/u/20080416/15/1ce087cd-a02f-40ac-a863-f5fe2bb11e9c.html?272833094
可是在函数调用时有出现了问题,发现该函数不能以子查询出现在查询中:
函数调用
select min(DB) from dbo.Getdb('0200-35259250 ','3230-00601010 ')
结果
5100
函数作为子查询调用
select (select min(DB) from Getdb(A.MD001,A.MD003))
from BOMMD A where MD003='3230-00601010 ' and MD001='1300-00601105 '
结果
Msg 170, Level 15, State 1, Line 1
第 1 行: '.' 附近有语法错误。

请高手解答,谢谢.
...全文
154 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
问题解决
谢谢无枪狙击手热心帮助!
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 happyflystone 的回复:]
select min(DB) from dbo.Getdb(A.MD001,A.MD003)

没看到你的getdb是什么函数 ,与临时表有什么 关系


我想: 你要的是min(db),
为什么 不函数直接返回出条件下(MD001,MD003)下的最小db

这样调的方法就是


SQL codeselect dbo.getdb(mdoo1,mdoo3)
from BOMMD
where MD001='1300-00601105' and MD003='3230-00601010'
[/Quote]

因为Getb返回的可能有多条记录,在函数中对多条记录删除留下一条?
我实际的需求是这样的:
需要从请购明细表上反映出每一个采购件都用在哪个工作中心.
分析如下:
请购单有记录订单号,由订单号可追溯成品编号
BOM表有记录主件工单别,工单别可反映工作中心

所以就写了函数依据请购明细表每行的成品编码及采购件编码,到BOM表进行循环查找,获取该采购件在该成品中的位置并返回工单别.
-狙击手- 2008-04-25
  • 打赏
  • 举报
回复
这样调的方法就是


SQL codeselect dbo.getdb(mdoo1,mdoo3)
from BOMMD
where MD001='1300-00601105' and MD003='3230-00601010'

-狙击手- 2008-04-25
  • 打赏
  • 举报
回复
ALTER FUNCTION [dbo].[Getdb](@part1 varchar(20),@part2 varchar(20)) 
RETURNS varchar(4)
AS
BEGIN
declare @i int
declare @t table(reno int,P1 CHAR(20),P2 CHAR(20),DB CHAR(4))
set @i=1
insert into @t
select @i as reno,@part1 as P1,MD003 as P2,MC005 as DB
from BOMMD A
left join BOMMC B on A.MD001=B.MC001
where MD001=@part1

while @@ROWCOUNT>0
begin
set @i=@i+1
insert into @t
select @i,@part1,MD003,MC005
from @t A
left join BOMMD B on A.P2=B.MD001
left join BOMMC C on B.MD001=C.MC001
where A.reno=@i-1 and not(B.MD001 is null)
end
delete @t where P2 <>@part2
declare @mindb varchar(4)
select @mindb = min(db) from @t

RETURN @mindb
end
-狙击手- 2008-04-25
  • 打赏
  • 举报
回复
改成如下:

ALTER FUNCTION [dbo].[Getdb](@part1 varchar(20),@part2 varchar(20)) 
RETURNS varchar(4)@t table(reno int,P1 CHAR(20),P2 CHAR(20),DB CHAR(4))
AS
BEGIN
declare @i int
declare @t table(reno int,P1 CHAR(20),P2 CHAR(20),DB CHAR(4))
set @i=1
insert into @t
select @i as reno,@part1 as P1,MD003 as P2,MC005 as DB
from BOMMD A
left join BOMMC B on A.MD001=B.MC001
where MD001=@part1

while @@ROWCOUNT>0
begin
set @i=@i+1
insert into @t
select @i,@part1,MD003,MC005
from @t A
left join BOMMD B on A.P2=B.MD001
left join BOMMC C on B.MD001=C.MC001
where A.reno=@i-1 and not(B.MD001 is null)
end
delete @t where P2 <>@part2
declare @mindb varchar(4)
select @mindb = min(db) from @t

RETURN @mindb
end

调用:


select dbo.getdb(mdoo1,mdoo3)
from BOMMD
where MD001='1300-00601105' and MD003='3230-00601010'


-狙击手- 2008-04-25
  • 打赏
  • 举报
回复
select min(DB) from dbo.Getdb(A.MD001,A.MD003)

没看到你的getdb是什么函数 ,与临时表有什么 关系


我想: 你要的是min(db),
为什么 不函数直接返回出条件下(MD001,MD003)下的最小db

这样调的方法就是

select dbo.getdb(mdoo1,mdoo3)
from BOMMD
where MD001='1300-00601105' and MD003='3230-00601010'
flairsky 2008-04-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 happyflystone 的回复:]
改成标量函数才行
[/Quote]
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
ALTER FUNCTION [dbo].[Getdb](@part1 varchar(20),@part2 varchar(20))
RETURNS @t table(reno int,P1 CHAR(20),P2 CHAR(20),DB CHAR(4))
AS
BEGIN
declare @i int
set @i=1
insert into @t
select @i as reno,@part1 as P1,MD003 as P2,MC005 as DB
from BOMMD A
left join BOMMC B on A.MD001=B.MC001
where MD001=@part1

while @@ROWCOUNT>0
begin
set @i=@i+1
insert into @t
select @i,@part1,MD003,MC005
from @t A
left join BOMMD B on A.P2=B.MD001
left join BOMMC C on B.MD001=C.MC001
where A.reno=@i-1 and not(B.MD001 is null)
end
delete @t where P2<>@part2
RETURN
end
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
改成标量函数?
那之前的函数中不能使用临时表的问题又如何解决?
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
函数意思不说,大家看看这几个查询
1.函数单独调用
select min(DB) from dbo.Getdb('1300-00601105 ','3230-00601010 ')
结果:
5100
2.所使用的查询
select MD001,MD003
from BOMMD where MD001='1300-00601105 ' and MD003='3230-00601010 '
结果
MD001 MD003
1300-00601105 3230-00601010
3.函数作为上面查询的子查询
select A.*,(select min(DB) from dbo.Getdb(A.MD001,A.MD003)) AS t
from BOMMD A where MD001='1300-00601105 ' and MD003='3230-00601010 '
结果
Msg 170, Level 15, State 1, Line 1
第 1 行: '.' 附近有语法错误。

这不是很奇怪吗?
-狙击手- 2008-04-25
  • 打赏
  • 举报
回复
改成标量函数才行
ojuju10 2008-04-25
  • 打赏
  • 举报
回复

--少了个对象的所有者dbo
select (select min(DB) from dbo.Getdb(A.MD001,A.MD003))
from BOMMD A where MD003='3230-00601010' and MD001='1300-00601105'
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
分拆函数之前用过,没有问题
不过奇怪这个函数就不能用
dawugui 2008-04-25
  • 打赏
  • 举报
回复
不用发短信了.打不开,打开了也看不到内容.

函数可以用于子查询.
至于你的具体内容就不知道了.
是不是你函数调用本身就不对.
wdsimon 2008-04-25
  • 打赏
  • 举报
回复
自定义Getdb是依据传入的参数最顶层主件品号和元件品号获取该元件品号当前层主件品号的工单单别
比如:
C001->B001.....->A001
函数得到B001的工单单别为5100
dawugui 2008-04-25
  • 打赏
  • 举报
回复

/*
标题:分解字符串并查询相关数据
作者:爱新觉罗.毓华
时间:2008-03-18
地点:广东深圳
说明:通过使用函数等方法分解字符串查询相关数据。

问题:通过分解一个带某种符号分隔的字符串在数据库中查找相关数据。
例如 @str = '1,2,3',查询下表得到记录1,4,5,6
ID TypeID
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
6 6,7
*/
-----------------------------
create table tb (ID int , TypeID varchar(30))
insert into tb values(1 , '1,2,3,4,5,6,7,8,9,10,11,12')
insert into tb values(2 , '2,3')
insert into tb values(3 , '3,7,8,9')
insert into tb values(4 , '2,6')
insert into tb values(5 , '4,5')
insert into tb values(6 , '6,7')
go
-----------------------------
--如果仅仅是一个,如@str = '1'.
declare @str as varchar(30)
set @str = '1'
select * from tb where charindex(',' + @str + ',' , ',' + TypeID + ',') > 0
select * from tb where ',' + TypeID + ',' like '%,' + @str + ',%'
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
(所影响的行数为 1 行)
*/

-----------------------------
--如果包含两个,如@str = '1,2'.
declare @str as varchar(30)
set @str = '1,2'
select * from tb where charindex(',' + left(@str , charindex(',' , @str) - 1) + ',' , ',' + typeid + ',') > 0 or
charindex(',' + substring(@str , charindex(',' , @str) + 1 , len(@str)) + ',' , ',' + typeid + ',') > 0
select * from tb where ',' + typeid + ',' like '%,' + left(@str , charindex(',' , @str) - 1) + ',%' or
',' + typeid + ',' like '%,' + substring(@str , charindex(',' , @str) + 1 , len(@str)) + ',%'
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
4 2,6
(所影响的行数为 3 行)
*/

-------------------------------------------
--如果包含三个或四个,用PARSENAME函数来处理.
declare @str as varchar(30)
set @str = '1,2,3,4'
select * from tb where
charindex(',' + parsename(replace(@str , ',' , '.') , 4) + ',' , ',' + typeid + ',') > 0 or
charindex(',' + parsename(replace(@str , ',' , '.') , 3) + ',' , ',' + typeid + ',') > 0 or
charindex(',' + parsename(replace(@str , ',' , '.') , 2) + ',' , ',' + typeid + ',') > 0 or
charindex(',' + parsename(replace(@str , ',' , '.') , 1) + ',' , ',' + typeid + ',') > 0
select * from tb where
',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 4) + ',%' or
',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 3) + ',%' or
',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 2) + ',%' or
',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 1) + ',%'
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/

---------------------------------------
--如果超过四个,则只能使用函数或动态SQL来分解并查询数据。
/*
名称:fn_split函数.
功能:实现字符串分隔功能的函数
*/
create function dbo.fn_split(@inputstr varchar(8000), @seprator varchar(10))
returns @temp table (a varchar(200))
as
begin
declare @i int
set @inputstr = rtrim(ltrim(@inputstr))
set @i = charindex(@seprator , @inputstr)
while @i >= 1
begin
insert @temp values(left(@inputstr , @i - 1))
set @inputstr = substring(@inputstr , @i + 1 , len(@inputstr) - @i)
set @i = charindex(@seprator , @inputstr)
end
if @inputstr <> '\'
insert @temp values(@inputstr)
return
end
go

--调用
declare @str as varchar(30)
set @str = '1,2,3,4,5'

select distinct m.* from tb m,
(select * from dbo.fn_split(@str,',')) n
where charindex(',' + n.a + ',' , ',' + m.typeid + ',') > 0

drop table tb
drop function dbo.fn_split

/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/

------------------------------------------
--使用动态SQL的语句。
declare @str varchar(200)
declare @sql as varchar(1000)
set @str = '1,2,3,4,5'
set @sql = 'select ''' + replace(@str , ',' , ''' as id union all select ''')
set @sql = @sql + ''''
set @sql = 'select distinct a.* from tb a , (' + @sql + ') b where charindex(' + ''','' + b.id + ' + ''',''' + ' , ' + ''','' + a.typeid + ' + ''',''' + ') > 0 '
exec (@sql)
/*
ID TypeID
----------- ------------------------------
1 1,2,3,4,5,6,7,8,9,10,11,12
2 2,3
3 3,7,8,9
4 2,6
5 4,5
(所影响的行数为 5 行)
*/



看后半部分的:

--调用
declare @str as varchar(30)
set @str = '1,2,3,4,5'

select distinct m.* from tb m,
(select * from dbo.fn_split(@str,',')) n
where charindex(',' + n.a + ',' , ',' + m.typeid + ',') > 0
dawugui 2008-04-25
  • 打赏
  • 举报
回复
函数能用于子查询.

至于你函数的意思,我没看懂.

34,575

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧