web-dev-qa-db-ja.com

SQL:ストアドプロシージャの句:値を渡す方法

パラメータとしてストアドプロシージャに渡される一部のユーザーIDについて、ユーザーテーブルからユーザーレコードを選択して返すSQL Server 2005ストアドプロシージャを記述したいと思います。

これを行う方法 ?

ユーザーIDをカンマで区切られた文字列として渡すことができます。使用できるように

select * 
from users 
where userid in (userids)

例えば。 :id 5、6、7、8、9のレコードを選択したい

ストアドプロシージャの記述方法

17
Shyju

SQL Server 2005については、Erland Sommarskogの優れた SQL Server 2005の配列とリスト の記事をご覧ください。SQLServer 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)

詳細はこちら こちら

マーク

25
marc_s

このように使用するだけで機能します

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

動的SQLを使用できます。 inステートメントを変数を介してSql SPに渡し、SQLのクエリに連結して、sp_execute sqlを使用して実行します。

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

参照 これに対する私の以前の答え

これは最高の情報源です:

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

分割関数を作成し、次のように使用します。

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

私は数表アプローチを好む

この方法を機能させるには、次の1回のタイムテーブル設定を行う必要があります。

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,,,')

出力:

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
5
KM.

T-SQLを想定すると、このNice関数(テーブルを返す)を使用できます。

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

ストアドファンクションを変更して、スペースで区切られた文字列ではなく、コンマで区切られた文字列を処理できます。

ストアドファンクションが不要/使用できない場合は、必要に応じてストアドプロシージャ内にそのコードを含めることができます。

編集:これは文字列連結よりも信じられないほどパフォーマンスが優れています。

3
Alex Bagnolini

これを試してみてください

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

早くて汚い.

CREATE PROCEDURE SelectUsers (@UserIds VARCHAR(8000))
AS
SELECT * FROM Users 
WHERE userid IN (SELECT CONVERT(VARCHAR(8000), value) FROM STRING_SPLIT(@UserIds, ','))
EXEC SelectUsers @UserIds = 'a1b2,c3d4,e5f6'
0
yakult