SQL:在存储过程子句:如何通过价值(SQL : in clause in stored proce

2019-07-21 02:29发布

我想写一个SQL Server 2005的存储过程,这将选择并返回从用户表中的用户记录一些用户ID被传递到存储过程作为参数。

这该怎么做 ?

我可以通过用户ID作为由逗号分隔的字符串。 所以,我可以使用

select * 
from users 
where userid in (userids)

例如:我想选择的ID记录5,6,7,8,9

如何编写存储过程?

Answer 1:

对于SQL Server 2005中,检查出厄兰Sommarskog出色的数组和列表在SQL Server 2005中的文章这表明一些技巧如何对付列表和数组在SQL Server 2005(他也有另一篇文章为SQL Server 2000)。

如果你可以升级到SQL Server 2008中,你可以使用所谓的“表值参数”的新功能:

首先,创建一个用户定义的表型

CREATE TYPE dbo.MyUserIDs AS TABLE (UserID INT NOT NULL)

其次,使用该表型在存储过程作为参数:

CREATE PROC proc_GetUsers @UserIDTable MyUserIDs READONLY 
AS
SELECT * FROM dbo.Users
    WHERE userid IN (SELECT UserID FROM @UserIDTable)

查看详情这里 。



Answer 2:

只要使用它像这样将工作

Create procedure sp_DoctorList 
@userid varchar(100)
as 
begin
exec ('select * from doctor where userid in ( '+ @userid +' )')
end


Answer 3:

你可以使用动态SQL。 通过变量传递中陈述到SQL SP和它连接成的SQL查询和使用SQL sp_execute执行

create procedure myproc(@clause varchar(100)) as 
begin
  exec sp_executesql 'select * from users where userid in ( ' + @clause +' )'
end


Answer 4:

看到我以前的答案,这

这是最好的来源:

http://www.sommarskog.se/arrays-in-sql.html

创建拆分功能,并使用它,如:

SELECT
    *
    FROM YourTable  y
    INNER JOIN dbo.splitFunction(@Parameter) s ON y.ID=s.Value

我更喜欢数字表方法

对于这种方法的工作,你需要做的这一次表设置:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.objects s1
    CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

一旦Numbers表格设置,创建此功能:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn  char(1)      --REQUIRED, the character to split the @List string on
    ,@List     varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN 
(

    ----------------
    --SINGLE QUERY-- --this will not return empty rows
    ----------------
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''

);
GO 

现在,您可以为CSV字符串容易分裂成表,并加入就可以了:

select * from dbo.FN_ListToTable(',','1,2,3,,,4,5,6777,,,')

OUTPUT:

ListValue
-----------------------
1
2
3
4
5
6777

(6 row(s) affected)

你可以在一个CSV字符串传递到一个程序和过程仅排在给定的ID:

SELECT
    y.*
    FROM YourTable y
        INNER JOIN dbo.FN_ListToTable(',',@GivenCSV) s ON y.ID=s.ListValue


Answer 5:

假设T-SQL,你可以使用这个功能不错(返回表)。

DROP FUNCTION sp_ConvertStringToTable
GO
CREATE FUNCTION sp_ConvertStringToTable(@list ntext)
      RETURNS @tbl TABLE (Position INT IDENTITY(1, 1) NOT NULL,
                          Value INT NOT NULL) AS
   BEGIN
      DECLARE @pos      int,
              @textpos  int,
              @chunklen smallint,
              @str      nvarchar(4000),
              @tmpstr   nvarchar(4000),
              @leftover nvarchar(4000)

      SET @textpos = 1
      SET @leftover = ''
      WHILE @textpos <= datalength(@list) / 2
      BEGIN
         SET @chunklen = 4000 - datalength(@leftover) / 2
         SET @tmpstr = ltrim(@leftover + substring(@list, @textpos, @chunklen))
         SET @textpos = @textpos + @chunklen

         SET @pos = charindex(' ', @tmpstr)
         WHILE @pos > 0
         BEGIN
            SET @str = substring(@tmpstr, 1, @pos - 1)
            INSERT @tbl (Value) VALUES(convert(int, @str))
            SET @tmpstr = ltrim(substring(@tmpstr, @pos + 1, len(@tmpstr)))
            SET @pos = charindex(' ', @tmpstr)
         END

         SET @leftover = @tmpstr
      END

      IF ltrim(rtrim(@leftover)) <> ''
         INSERT @tbl (Value) VALUES(convert(int, @leftover))

      RETURN
   END   
GO

通过这种方式:

SELECT * FROM Users 
WHERE userid IN 
( SELECT Value FROM sp_ConvertStringToTable('1 2 3') )

您可以更改存储的功能与逗号分隔字符串代替空格隔开的人一起工作。

如果你不想/不能使用存储功能,您可以包括存储过程中它的代码需要的地方。

编辑:这是令人难以置信的比字符串连接更好的性能。



Answer 6:

试试这个这个工作对我来说

DECLARE @InClause NVARCHAR(100)
SET @InClause = 'tom,dick,harry'
DECLARE @SafeInClause NVARCHAR(100)
SET @SafeInClause = ',' + @InClause + ',' 
SELECT * FROM myTable WHERE PATINDEX(',' + myColumn + ',', @SafeInClause) > 0


Answer 7:

您还可以使用FIND_IN_SET代替。 请参阅下面的查询

create procedure myproc(IN in_user_ids varchar(100)) 
begin
   select * from users where FIND_IN_SET(userid, in_user_ids);
end


文章来源: SQL : in clause in stored procedure:how to pass values