【问题标题】:Using uniqueidentifier with IN Clause in SQL server在 SQL Server 中使用带有 IN 子句的 uniqueidentifier
【发布时间】:2014-04-16 05:41:11
【问题描述】:

我有一个存储过程,它将一串 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 进行比较。 谁知道怎么解决这个问题?

【问题讨论】:

  • 为什么不对所有值使用单独的变量并给出 IN (@Param1, @Param2, @Param3...) 之类的范围?
  • SQL,与大多数语言一样,当传递 single 参数是一个字符串时,不会检查字符串的内容,查找逗号,并决定改为处理single 参数作为 multiple 参数,甚至可能是不同的数据类型。为什么会这样?
  • 最好将存储过程定义为接受适当数据类型的参数,该数据类型设计用于保存多个单独的值。 SQL Server 中有两种这样的类型 - 表值参数或 xml。

标签: sql sql-server stored-procedures uniqueidentifier in-clause


【解决方案1】:
declare @sql varchar(max)
set @sql='SELECT * FROM dbo.Table1 WHERE 
    TableGUID IN ('+@Param+') '

exec (@sql)

【讨论】:

    【解决方案2】:

    除了 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'''

    注意列表的最后一个逗号。它应该被删除。

    【讨论】:

    • 这也不起作用出现错误“从字符串转换为唯一标识符时转换失败。”
    【解决方案3】:

    我们不能这样做,因为 SQL 没有列表、数组或其他有用的数据结构的概念——它只知道表(和基于表的信息),因此它在编译时将字符串列表转换为表结构该命令 - 它无法编译变量字符串,因此它会抱怨并且您会生气。或者至少,我愿意。

    我们要做的是首先将逗号分隔的值转换为表格。我的初始版本是内联的,而且相当混乱,所以我将它重新设计成一个用户函数,让它更通用。

    使用 [测试] 去

    CREATE 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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      • 2011-02-26
      • 2016-05-13
      • 1970-01-01
      相关资源
      最近更新 更多