2017-02-24 20 views
6

Tìm cách chuyển danh sách User ID để trả về tên danh sách. Tôi có một kế hoạch để xử lý các tên đầu ra (với một cái gì đó COALESCE hoặc khác) nhưng cố gắng tìm cách tốt nhất để vượt qua trong danh sách các ID người dùng. Các ruột của sproc của tôi sẽ giống như thế này:Làm cách nào để chuyển danh sách dưới dạng tham số trong quy trình được lưu trữ?

create procedure [dbo].[get_user_names] 
@user_id_list, --which would equal a list of incoming ID numbers like (5,44,72,81,126) 
@username varchar (30) output 
as 
select last_name+', '+first_name 
from user_mstr 
where user_id in @user_id_list 

Đi qua các giá trị cho @user_id_list là mối quan tâm chính của tôi ở đây.

+5

Tôi sẽ không chuyển vào danh sách ID, tôi sẽ tạo loại bảng do người dùng xác định, chèn giá trị vào đó và chuyển biến đó vào proc. Sau đó bạn có thể thực hiện một 'JOIN' vào bảng. – Siyual

+1

thử tìm tại đây: http://stackoverflow.com/questions/7097079/c-sharp-sql-server-passing-a-list-to-a-stored-procedure –

+0

tôi đồng ý với các tham số bảng ... thứ hai tôi sẽ sử dụng một splitter chuỗi và như là một phương sách cuối cùng ... sql năng động. Câu hỏi tương tự vừa được đăng [tại đây] (http://stackoverflow.com/questions/42448333/using-a-string-which-comprises-of-values-in-a-query) – scsimon

Trả lời

1

Bạn có thể thử này:

create procedure [dbo].[get_user_names] 
    @user_id_list varchar(2000), -- You can use any max length 

    @username varchar (30) output 
    as 
    select last_name+', '+first_name 
    from user_mstr 
    where user_id in (Select ID from dbo.SplitString(@user_id_list, ',')) 

Và đây là người dùng được xác định chức năng cho SplitString:

Create FUNCTION [dbo].[SplitString] 
( 
     @Input NVARCHAR(MAX), 
     @Character CHAR(1) 
) 
RETURNS @Output TABLE (
     Item NVARCHAR(1000) 
) 
AS 
BEGIN 
     DECLARE @StartIndex INT, @EndIndex INT 

     SET @StartIndex = 1 
     IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character 
     BEGIN 
      SET @Input = @Input + @Character 
     END 

     WHILE CHARINDEX(@Character, @Input) > 0 
     BEGIN 
      SET @EndIndex = CHARINDEX(@Character, @Input) 

      INSERT INTO @Output(Item) 
      SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1) 

      SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input)) 
     END 

     RETURN 
END 
+1

có thể chúng sẽ cần chức năng chia chuỗi ..... – scsimon

+0

' dbo.SplitString' không phải là hàm bên trong. –

+1

Đó có lẽ là chậm nhất bạn có thể nhận được cho loại chức năng đó.Kiểm tra ở đây cho một số tùy chọn khác: [Tách chuỗi đúng cách - hoặc cách tốt nhất tiếp theo - Aaron Bertrand] (https://sqlperformance.com/2012/07/t-sql-queries/split-strings) – SqlZim

0

Có lẽ bạn có thể sử dụng:

select last_name+', '+first_name 
from user_mstr 
where ',' + @user_id_list + ',' like '%,' + convert(nvarchar, user_id) + ',%' 
14

Các phương pháp ưa thích cho đi qua một mảng các giá trị cho một thủ tục lưu sẵn trong máy chủ SQL là sử dụng các tham số có giá trị bảng.

Trước tiên, bạn xác định loại như thế này:

CREATE TYPE UserList AS TABLE (UserID INT); 

Sau đó, bạn sử dụng loại rằng trong thủ tục lưu trữ:

create procedure [dbo].[get_user_names] 
@user_id_list UserList READONLY, 
@username varchar (30) output 
as 
select last_name+', '+first_name 
from user_mstr 
where user_id in (SELECT UserID FROM @user_id_list) 

Vì vậy, trước khi bạn gọi đó là thủ tục lưu trữ, bạn điền vào một biến bảng:

DECLARE @UL UserList; 
INSERT @UL VALUES (5),(44),(72),(81),(126) 

Và cuối cùng gọi cho SP:

EXEC dbo.get_user_names @UL, @username OUTPUT; 
1

Theo như tôi có thể biết, có ba ứng cử viên chính: Tham số Bảng giá trị, chuỗi danh sách phân cách và chuỗi JSON.

Kể từ năm 2016, bạn có thể sử dụng được xây dựng trong STRING_SPLIT nếu bạn muốn con đường phân định: https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

Đó có lẽ sẽ là đơn giản nhất phương pháp đơn giản dễ nhất//.

Cũng kể từ năm 2016, JSON có thể được thông qua như là một nvarchar và sử dụng với OPENJSON: https://docs.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql

Đó có thể là tốt nhất nếu bạn có một dữ liệu có cấu trúc hơn thiết để vượt qua mà có thể biến đáng kể trong sơ đồ của nó.

TVP, có vẻ như là cách kinh điển để truyền các thông số có cấu trúc hơn và chúng vẫn tốt nếu bạn cần cấu trúc đó, nhân chứng và kiểm tra giá trị/kiểu cơ bản. Mặc dù vậy, họ có thể hơi cồng kềnh hơn ở phía người tiêu dùng. Nếu bạn không có 2016+, đây có thể là tùy chọn mặc định/tốt nhất.

Tôi nghĩ rằng đó là sự cân bằng giữa bất kỳ cân nhắc cụ thể nào cũng như sở thích của bạn về cấu trúc thông số của bạn, nghĩa là ngay cả khi bạn có 2016+, bạn có thể nêu rõ loại/lược đồ tham số thay vì truyền một chuỗi và phân tích cú pháp bằng cách nào đó.

0

Bạn có thể sử dụng phương pháp đơn giản 'inline' này để xây dựng một tham số string_list_type (công trình trong SQL Server 2014):

declare @p1 dbo.string_list_type 
insert into @p1 values(N'myFirstString') 
insert into @p1 values(N'mySecondString') 

Ví dụ sử dụng khi thực hiện một proc lưu trữ:

exec MyStoredProc @[email protected] 
0

tôi giải quyết vấn đề này thông qua các vấn đề sau:

  1. Trong C# tôi đã tạo biến chuỗi.

chuỗi userId = "";

  1. Tôi đặt mục danh sách của mình trong biến này. Tôi đã tách ','.

ví dụ: trong C#

userId= "5,44,72,81,126"; 

và Send to SQL-Server

SqlParameter param = cmd.Parameters.AddWithValue("@user_id_list",userId); 
  1. Tôi Tạo Tách chức năng trong SQL-server để chuyển đổi nhận của tôi L ist (rằng đó là loại NVARCHAR(Max)) để Bảng.
CREATE FUNCTION dbo.SplitInts 
( 
    @List  VARCHAR(MAX), 
    @Delimiter VARCHAR(255) 
) 
RETURNS TABLE 
AS 
    RETURN (SELECT Item = CONVERT(INT, Item) FROM 
     (SELECT Item = x.i.value('(./text())[1]', 'varchar(max)') 
     FROM (SELECT [XML] = CONVERT(XML, '<i>' 
     + REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.') 
     ) AS a CROSS APPLY [XML].nodes('i') AS x(i)) AS y 
     WHERE Item IS NOT NULL 
); 
  1. Trong Thủ tục cửa hàng chính, sử dụng lệnh dưới đây, tôi sử dụng danh sách nhập cảnh.

SELECT user_id = Item FROM dbo.SplitInts (@user_id_list, ',');

Các vấn đề liên quan