希望传递用户ID列表以返回列表名称。我有计划处理输出的名称(使用COALESCE或其他东西),但试图找到传递用户ID列表的最佳方法。 我的sproc的内容看起来像这样:
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
传递@user_id_list的值是我的主要关注点。
答案 0 :(得分:32)
The preferred method for passing an array of values to a stored procedure in SQL server is to use table valued parameters.
First you define the type like this:
CREATE TYPE UserList AS TABLE ( UserID INT );
Then you use that type in the stored procedure:
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)
So before you call that stored procedure, you fill a table variable:
DECLARE @UL UserList;
INSERT @UL VALUES (5),(44),(72),(81),(126)
And finally call the SP:
EXEC dbo.get_user_names @UL, @username OUTPUT;
答案 1 :(得分:8)
据我所知,有三个主要的竞争者:表值参数,分隔列表字符串和JSON字符串。
自2016年以来,如果您想要分隔的路线,可以使用内置的STRING_SPLIT:https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
这可能是最简单/最简单/最简单的方法。
同样从2016年开始,JSON可以作为nvarchar传递并与OPENJSON一起使用:https://docs.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql
如果你有一个更结构化的数据集可以在其模式中显着变化,那么这可能是最好的。
似乎TVP似乎是传递更多结构化参数的规范方法,如果您需要结构,显式性和基本值/类型检查,它们仍然很好。不过,它们在消费者方面可能会稍微麻烦一些。如果您没有2016+,这可能是默认/最佳选择。我认为这是在任何这些具体考虑因素之间的权衡,以及您对明确的params结构的偏好,这意味着即使您有2016年以上,您可能更愿意明确说明其类型/架构。参数而不是传递一个字符串并以某种方式解析它。
答案 2 :(得分:3)
我通过以下方式解决了这个问题:
string userId =“”;
例如:在C#中
userId= "5,44,72,81,126";
并发送到SQL-Server
SqlParameter param = cmd.Parameters.AddWithValue("@user_id_list",userId);
NVARCHAR(Max)
)转换为表格。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 );
SELECT user_id = Item FROM dbo.SplitInts(@user_id_list,',');
答案 3 :(得分:2)
这对我来说是完美的工作。我希望这个完美的例子解决了很多用户的问题。
第 1 步 像这样在sql中创建引用表
Create TYPE dbo.tblNames
AS TABLE
(
[Name] nvarchar(max)
);
go
create TYPE dbo.tblNamesWithCols
AS TABLE
(
[Name] nvarchar(max)
);
go
第 2 步 使用这样的引用表参数创建存储过程
create proc syTest
@VarTbleNameList AS dbo.tblNames READONLY,
@VarTbleNameColsList AS dbo.tblNamesWithCols READONLY,
@VarWhereQuery nvarchar(max)
as
begin
......
...... End
**使用参数调用存储过程**
DECLARE @VarTbleList AS dbo.tblNames
INSERT INTO @VarTbleList
VALUES ( 'tblEmployes' )
INSERT INTO @VarTbleList
VALUES ( 'tblDepartments' )
INSERT INTO @VarTbleList
VALUES ( 'tblCities' )
DECLARE @VarTbleColList AS dbo.tblNamesWithCols
INSERT INTO @VarTbleColList
VALUES ( 'tblEmployes.EmployeId as empId;' )
INSERT INTO @VarTbleColList
VALUES ( 'tblEmployes.EmployeName as empName;' )
INSERT INTO @VarTbleColList
VALUES ( 'tblDepartments.DepartmentName as deptName;' )
INSERT INTO @VarTbleColList
VALUES ( 'tblDepartments.DepartmentId as deptId;' )
EXECUTE syTest @VarTbleList , @VarTbleColList , @VarWhereQuery ='test'
答案 4 :(得分:1)
你可以试试这个:
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, ',') )
这是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
答案 5 :(得分:1)
Azure DB,Azure Data WH和SQL Server 2016中的数据,您可以使用STRING_SPLIT获得与@sparrow描述的结果类似的结果。
从@sparrow回收代码
useDispatch
将值列表接受到存储过程中的简单有效的方法
答案 6 :(得分:1)
检查下面的代码这对我有用
@ManifestNoList VARCHAR(MAX)
WHERE
(
ManifestNo IN (SELECT value FROM dbo.SplitString(@ManifestNoList, ','))
)
答案 7 :(得分:0)
您可以使用这种简单的“内联”方法构造string_list_type参数(适用于SQL Server 2014):
declare @p1 dbo.string_list_type
insert into @p1 values(N'myFirstString')
insert into @p1 values(N'mySecondString')
执行存储过程时的示例:
exec MyStoredProc @MyParam=@p1
答案 8 :(得分:0)
正确的方法是创建用户定义的数据类型:
CREATE TYPE [dbo].[IntArray] AS TABLE
(
[ID] [INT] NULL
)
然后你可以使用这个自定义数据类型:
CREATE OR ALTER PROCEDURE [dbo].[sp_GetUserNames]
(
@userIds [IntArray] READONLY
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
"Name" = u.LastName + ', ' + u.FirstName
FROM dbo.User u
JOIN @userIds uid ON u.Id = uid.Id;
END
用法:
@DECLARE @result TABLE
(
Name NVARCHAR(max)
);
@DECLARE @ids [IntArray] = SELECT x.userId FROM dbo.sometable x;
SET @result = EXECUTE [dbo].[sp_GetUserNames] @userIds = @ids;
SELECT * FROM @result;