我有一个存储过程,它将GUID字符串作为输入,并从GUID为IN (@Param)的表中进行选择。
@Param = 'b2e16cdc-1f1b-40e2-a979-f87a6a2457af,
c275dd13-bb54-4b8c-aa12-220b5980cabd,
af3552ec-37b1-4a76-81ad-1bd6b8c4cd6c,
3a7fda02-558b-49a9-a870-30350254d8c0,'
SELECT * FROM dbo.Table1 WHERE
TableGUID IN (@Param)
然而,我注意到查询返回值,只有当第一个GUID匹配,否则它不会返回任何东西。这意味着它只比较字符串中的第一个GUID。有人知道怎么解决这个问题吗?
declare @sql varchar(max)
set @sql='SELECT * FROM dbo.Table1 WHERE
TableGUID IN ('+@Param+') '
exec (@sql)
我们不能这样做,因为SQL没有列表、数组或其他有用的数据结构的概念——它只知道表(和基于表的信息),所以它在编译命令时将字符串列表转换为表结构——而且它不能编译可变字符串,所以它会抱怨,你会很恼火。或者至少,我知道。
我们首先要做的是将逗号分隔的值转换成一个表。我最初的版本是内联的,相当混乱,所以我把它重新设计成一个用户函数,使它更通用一些。
USE [Testing] GOCREATE FUNCTION [dbo].[VarcharToTable] (@InStr NVARCHAR(MAX))
RETURNS @TempTab TABLE
(id UNIQUEIDENTIFIER NOT NULL)
AS
BEGIN
;-- Ensure input ends with comma
SET @InStr = REPLACE(@InStr + ',', ',,', ',')
DECLARE @SP INT
DECLARE @VALUE NVARCHAR(MAX)
WHILE PATINDEX('%,%', @INSTR ) <> 0
BEGIN
SELECT @SP = PATINDEX('%,%',@INSTR)
SELECT @VALUE = LEFT(@INSTR , @SP - 1)
SELECT @INSTR = STUFF(@INSTR, 1, @SP, '')
INSERT INTO @TempTab(id) VALUES (@VALUE)
END
RETURN
END
GO
这创建了一个用户函数,该函数接受逗号分隔的值字符串,并将其转换为SQL能够理解的表—只需传递字符串,它就可以完成所有操作。它的工作原理很明显,唯一的复杂性是REPLACE部分,它通过附加一个逗号来确保字符串以单个逗号结束,并从字符串中删除所有双逗号。如果不这样做,while循环就会变得更难处理,因为最后的数字可能有也可能没有结束逗号,而这必须单独处理。
DECLARE @LIST NVARCHAR(MAX)
SET @LIST = '973150D4-0D5E-4AD0-87E1-037B9D4FC03B,973150d4-0d5e-4ad0-87e1-037b9d4fc03c'
SELECT Id, Descr FROM TableA WHERE Id IN (SELECT * FROM dbo.VarcharToTable(@LIST))
除了MikkaRin的回答:GUID必须在撇号中打开,所以参数中的值应该看起来像'b2e16cdc-1f1b-40e2-a979-f87a6a2457af',
'c275dd13-bb54-4b8c-aa12-220b5980cabd',
'af3552ec-37b1-4a76-81ad-1bd6b8c4cd6c',
'3a7fda02-558b-49a9-a870-30350254d8c0'
最后,你必须传递这样的东西:
@Param = '''b2e16cdc-1f1b-40e2-a979-f87a6a2457af'',
''c275dd13-bb54-4b8c-aa12-220b5980cabd'',
''af3552ec-37b1-4a76-81ad-1bd6b8c4cd6c'',
''3a7fda02-558b-49a9-a870-30350254d8c0'''
注意列表最后一个逗号。