C# SQL:如何执行返回列为“IN”参数的值的存储过程?
我有一个表,当特定的列值在parameter not=parameter中时,我需要存储过程返回所有行C# SQL:如何执行返回列为“IN”参数的值的存储过程?,c#,sql,sql-server,stored-procedures,C#,Sql,Sql Server,Stored Procedures,我有一个表,当特定的列值在parameter not=parameter中时,我需要存储过程返回所有行 USE [MyDatabase] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[TestGetDataInParameter] @MyParameter nvarchar(MAX) AS BEGIN SELECT * FROM MyTable WHE
USE [MyDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[TestGetDataInParameter]
@MyParameter nvarchar(MAX)
AS
BEGIN
SELECT *
FROM MyTable
WHERE MyColum IN (@MyParameter)
END
我有执行此存储过程的C代码,我不知道应该以何种格式传递参数才能正确执行查询。一如既往,答案是,这取决于具体情况。所以,首先。。。当前显示的语法
WHERE MyColum IN (@MyParameter)
如果尝试传递多个值,则将失败。如果不想从应用程序中传递逗号分隔的列表或数组,则首先需要将字符串解析为单独的值。如果您使用的是SQL Server 2016或Azure,那么这项任务就轻而易举了。只需使用STRING_SPLIT函数。如果你没有,你会想找到一个好的字符串拆分器。我最喜欢的是,或者如果你对CRL组件感到满意的话,有一个据说比周围任何东西都快的CRL组件
所以,问题1解决了。。。问题2,如果某个特定值包含在值字符串中,您希望基本上完全忽略筛选器
同样,一旦字符串被拆分,查找值就变得非常容易了。您可以使用或@SomeParameter=MagicValue禁用过滤器
下面应该说明这个想法
DECLARE @ValuesList VARCHAR(1000) = '-1,1048309,1308584,1491312,1959807,2024608,2428302,2552655,2617456,2623776';
IF OBJECT_ID('tempdb..#ParameterValues', 'U') IS NOT NULL
DROP TABLE #ParameterValues;
SELECT Item = CAST(sc.Item AS INT) INTO #ParameterValues FROM dbo.SplitCSVToTable8K(@ValuesList, ',') sc;
DECLARE @GetAll BIT = 0; -- ( -1 is the "all" value from the input string )
SELECT @GetAll = 1 FROM #ParameterValues pv WHERE pv.Item = 1;
SELECT
*
FROM
sys.sysobjects o
LEFT JOIN #ParameterValues pv
ON o.id = pv.Item
WHERE
(
pv.Item IS NOT NULL
OR
@GetAll = 1
)
OPTION(RECOMPILE);
请注意在查询中使用了OPTIONRECOMPILE。使用这样的可选参数将导致优化器忽略任何SEEK执行计划选项。OPTIONRECOMPILE允许优化器在创建计划之前等待并查看传递给参数的值(如果有),从而允许搜索操作。创建以下函数。。接受字符串的简单函数。。随着分离器,吐出一张桌子
CREATE FUNCTION [dbo].[F_SplitList](@String nvarchar(4000), @Delimiter char(1))
RETURNS @Results TABLE (value nvarchar(4000))
AS
BEGIN
DECLARE @INDEX INT
DECLARE @SLICE nvarchar(4000)
-- HAVE TO SET TO 1 SO IT DOESNT EQUAL Z
-- ERO FIRST TIME IN LOOP
SELECT @INDEX = 1
IF @String IS NULL RETURN
WHILE @INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT @INDEX = CHARINDEX(@Delimiter,@STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF @INDEX !=0
SELECT @SLICE = LEFT(@STRING,@INDEX - 1)
ELSE
SELECT @SLICE = @STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO @Results(value) VALUES(@SLICE)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX)
-- BREAK OUT IF WE ARE DONE
IF LEN(@STRING) = 0 BREAK
END
RETURN
END
然后你可以这样叫你的Where:
WHERE MyColum in (Select * from(dbo.F_SplitList(@MyParameter,','))
像这样传递MyParameter值:“var1,var2,var3”是的,在这种情况下,您必须使用split函数,并按照这里的说明进行操作 另一种方式,
declare @MyParameter varchar(50)='1,2,3'
declare @Sql nvarchar(max)=''
set @Sql=
N'SELECT * FROM HumanResources.Employee
WHERE BusinessEntityID IN ('+@MyParameter+')'
exec sp_executesql @Sql, N'@MyParameter1 varchar(50)', @MyParameter1 = @MyParameter
试试这个:
USE [MyDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter PROCEDURE [dbo].[TestGetDataInParameter] @MyParameter nvarchar(MAX)
AS
BEGIN
declare @str nvarchar(MAX)
set @str = 'SELECT * FROM MyTable
WHERE MyColum IN ('+@MyParameter+')'
exec(@str)
print @str
END
exec [TestGetDataInParameter] "'abc','xyz'"
看起来MyColumn是varchar,所以您应该从CYeah以字符串的形式传递参数,我的意思是字符串应该像val1,val2,。。或者'val1','val2',我在询问应该发送到过程的输入格式。应该是-'val1','val2'。删除引号中的多余空格。如果没有动态SQL,这将不起作用,因为无论您如何格式化字符串,SQL都会将其解释为字符串。。。实际上,您应该传递一个datatable,并使存储过程的参数为TVP,但如果失败,则需要一个字符串拆分器。不管你做什么,你都需要重建存储过程的编写方式。@ZLK是的,我尝试过的所有格式都不起作用,你能帮我修改存储过程吗?这将是伟大的,如果你能提供一个例子或链接,显示如何做到这一点的例子。