Har*_*run 5 sql-server stored-procedures dynamic-sql
我的存储过程如下,
-- Add the parameters for the stored procedure here
@FromDate datetime,
@ToDate datetime
--Select query
DECLARE @query nvarchar(max)
set @query='SELECT [col1]
FROM [Table1]
WHERE ([col2] BETWEEN '''+@FromDate+''' AND'''+@ToDate+''')'
execute sp_executesql @query
Run Code Online (Sandbox Code Playgroud)
执行此字符串查询会导致以下错误,
"从字符串转换日期和/或时间时转换失败。 "
哪位大神帮我解决一下...
bil*_*nkc 11
根本问题是 TSQL 不能将日期时间(或整数或浮点数)隐式转换为字符数据类型。它实际上是倒退的,它尝试根据数据类型优先规则将字符数据隐式转换为日期时间(整数/浮点值)。这是您的错误消息顺便告诉您的,它无法将字符串转换为日期时间值。您必须明确要求它将值混搭为字符串。
这个例子用整数演示了主体,因为它们更容易理解预期值。
DECLARE
@stringInt nvarchar(3)
, @intint int
SELECT
@stringInt = N'3'
, @intint = 5
SELECT
@stringInt + @intint AS implicit_conversion
, @stringInt + CAST(@intint AS nvarchar(5)) AS explicit_conversion
Run Code Online (Sandbox Code Playgroud)
隐式转换的值显示 @stringint 首先转换为整数,然后 + 被视为数字加法,结果为 8。@intint 显式转换为字符数据类型导致 + 符号被视为与返回 35 的字符串
implicit_conversion explicit_conversion
------------------- -------------------
8 35
Run Code Online (Sandbox Code Playgroud)
要解决您提供的问题,您必须将日期时间值显式转换为字符类型,以便可以按预期连接查询字符串。
set @query='SELECT [col1]
FROM [Table1]
WHERE ([col2] BETWEEN ''' + CONVERT(nvarchar(24), @FromDate, 121) +''' AND'''+ CONVERT(nvarchar(24), @ToDate, 121) +''')'
Run Code Online (Sandbox Code Playgroud)
但是如上所述,出于多种原因,您确实不想这样做,SQL 注入就是其中之一。当您在 TSQL 中对查询字符串进行切片和切块时,它还会使您的维护变得更加困难。
更好的方法是参数化您的查询并使用sp_executesql的强大功能。sp_executesql 参数的一个好处是您不必使用提供的所有参数。根据您真正想做的事情,这可能是有益的。
示例表和数据
CREATE TABLE
dbo.table1
(col1 int, col2 datetime)
INSERT INTO
dbo.table1
SELECT
3, '2009-04-06'
UNION ALL SELECT
1, '2001-09-11'
Run Code Online (Sandbox Code Playgroud)
使用参数演示
DECLARE
@FromDate datetime,
@ToDate datetime
SELECT
@FromDate = '2005-03-17'
, @ToDate = current_timestamp
DECLARE
@query nvarchar(max)
SET @query = N'
SELECT [col1]
FROM [Table1]
WHERE ([col2] BETWEEN @start AND @end)'
-- gratuitous use of parameter assignment here
-- could just as easily used @FromDate and @ToDate
-- in the @query and the parameter list
EXECUTE sp_executesql
@query
, N'@start datetime, @end datetime'
, @start = @FromDate
, @end = @ToDate
Run Code Online (Sandbox Code Playgroud)
结果
col1
3
Run Code Online (Sandbox Code Playgroud)