das*_*das 2 sql t-sql sql-server
我有一个函数将一个sting数字列表转换为一个整数表:
USE [IFRS_Temp]
GO
/****** Object: UserDefinedFunction [dbo].[CSVToTable] Script Date: 01/12/2019 3:36:10 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[CSVToTable] (@InStr VARCHAR(MAX))
RETURNS @TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET @InStr = REPLACE(@InStr + ',', ',,', ',')
DECLARE @SP INT
DECLARE @VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', @INSTR ) <> 0
BEGIN
SELECT @SP = PATINDEX('%,%',@INSTR)
SELECT @VALUE = LEFT(@INSTR , @SP - 1)
SELECT @INSTR = STUFF(@INSTR, 1, @SP, '')
INSERT INTO @TempTab(id) VALUES (@VALUE)
END
RETURN
END
Run Code Online (Sandbox Code Playgroud)
declare @listOfIDs varchar(1000);
SET @listOfIDs = '5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61';
select id from [dbo].[CSVToTable] (@listOfIDs) --this code is ok5
Run Code Online (Sandbox Code Playgroud)
结果是正确的:
6
7
8
9
15
28
31
49
51
59
61
Run Code Online (Sandbox Code Playgroud)
这会引发错误:
exec('select id from [dbo].[CSVToTable] ('+@listOfIDs+')') -- error
Run Code Online (Sandbox Code Playgroud)
结果:
过程或函数dbo.CSVToTable指定了太多参数.
我需要第二个查询,因为我的查询是动态的.谢谢
只是
EXECUTE ('select id from [dbo].[CSVToTable] ('''+@listOfIDs+''')')
declare @listOfIDs varchar(1000);
Run Code Online (Sandbox Code Playgroud)
或者,哪种方式更好
SET @listOfIDs = '5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61';
EXECUTE sp_executesql N'select id from [dbo].[CSVToTable] (@listOfIDs)',
N'@listOfIDs VARCHAR(1000)',
@listOfIDs;
Run Code Online (Sandbox Code Playgroud)
过程或函数dbo.CSVToTable指定了太多参数.
因为你真的传递了太多的参数,所以需要更多,以了解这个运行这个查询并看看你真正传递给你的函数
SELECT 'select id from [dbo].[CSVToTable] ('+@listOfIDs+')';
Run Code Online (Sandbox Code Playgroud)
将返回(这是你真正想要执行的)
select id from [dbo].[CSVToTable] (5, 6, 7, 8, 9, 15, 28, 31, 49, 51, 59, 61)
Run Code Online (Sandbox Code Playgroud)
而不是(这是你需要的)
SELECT 'select id from [dbo].[CSVToTable] ('''+@listOfIDs+''')';
Run Code Online (Sandbox Code Playgroud)
sp_executesql比这更好exec?简单地说,EXEC将强制您将所有变量连接成一个单独的字符串,这是最糟糕的事情,这使得您的代码完全对SQL注入开放.请注意Bad Habits to Kick : Using EXEC() instead of sp_executesql,这并不意味着它sp_executesql是100%安全的,但它允许语句参数化而不是EXEC() dos,因此它比EXECSQL注入更安全.
最后,因为你标记
SQL服务器并且你没有指定版本,我建议你使用SPLIT_STRING()函数(2016+)rathar而不是你的版本,如果你没有2016+版本,那么创建你自己而不使用WHILE循环来获得更好的性能,导致WHILE循环将执行缓慢,因此你应该避免它.
例子:
| 归档时间: |
|
| 查看次数: |
597 次 |
| 最近记录: |