我有一个T-SQL存储过程,我需要将参数的值插入表中的文本字段。通过参数传入的值实际上是一个查询,我稍后将其作为动态SQL执行。当我输入一行没有任何引号或其他特殊字符如破折号( - )时,它可以正常工作。但是由于引号或特殊字符会引发它,因此引用或引用特殊字符。
存储过程的输入参数是:
@input_query text
我的价值是:
Select
t1.*, t2.name
from
nyc..sellers t1
right join
ark..buyers t2 on t1.id = t2.id
where
t1.date = 'period'
and t2.period between '2016-01-01' and '2016-12-31'
and t2.def = 'u'
当我尝试执行这样的存储过程时:
DECLARE @return_value int
EXEC @return_value = [dbo].[booksellers]
@input_query = N'Select t1.*, t2.name from nyc..sellers t1 right join ark..buyers t2 on
t1.id = t2.id where t1.date = 'period' and t2.period between '2016-01-01' and '2016-12-31' and t2.def = 'u''
SELECT 'Return Value' = @return_value
我收到以下错误:
在'期间'附近不正确的语法
我意识到这是因为引号没有被转义,即使它们是,下一个错误将是日期没有被转义等等。但我不能搞乱那个输入查询 - 它需要按原样插入。有没有办法让它发挥作用?
答案 0 :(得分:0)
答案是逃避撇号,如果要将文本分配给变量或插入数据库,则必须完成。
转义由查询解析器处理,而不是由处理器处理。当您查看使用转义撇号插入的数据或从数据库中检索它时,您可以使用单撇号将其返回。它不会影响您的数据。
如果我理解正确,您将该查询插入表中,以便以后可以查询该表并执行这些查询。排队报告程序的一些痛处?
这个概念证明查询证明了这可以用ESCAPED APOSTROPHES。我没有你的架构所以我不得不更改表的名称 它创建必要的表和模拟书店过程,将ESCAPED input_query插入表中。用3个不同的查询重复3次。然后我使用临时表和while循环来拉取这些查询并执行它们。
drop table t1;
create table t1 (
name varchar( 20 ),
id varchar( 20 ),
date varchar( 20 ),
rid int identity primary key
)
drop table t2;
create table t2 (
name varchar( 20 ),
id varchar( 20 ),
[period] datetime,
def varchar( 10 ),
rid int identity primary key
)
drop table QueryData;
create table QueryData (
query nvarchar(max),
rid int identity primary key
)
go
---- drop procedure dbo.booksellers;
go
create procedure dbo.booksellers (
@input_query nvarchar(max)
)
as
begin
declare @return int
insert into QueryData ( query ) values ( @input_query )
select @return = SCOPE_IDENTITY()
return @return
end
go
insert into t1 ( name, id, date ) values
( 'row1', 'some', 'period' ),
( 'row2', 'more', 'period' ),
( 'row3', 'even', 'not period' )
insert into t2 ( name, id, [period], def ) values
( 'period1', 'some', '2016-09-15 06:00', 'u' ),
( 'period2', 'more', '2016-09-15 07:00', 'u' ),
( 'period3', 'less', '2017-09-15 06:00', 'u' ),
( 'period1', 'some', '2017-09-15 06:00', 'u' ),
( 'period2', 'more', '2017-09-15 07:00', 'u' ),
( 'period3', 'less', '2017-09-15 06:00', 'u' ),
( 'period1', 'some', '2017-09-15 06:00', 'x' ),
( 'period2', 'more', '2017-09-15 07:00', 'x' ),
( 'period3', 'less', '2017-09-15 06:00', 'x' )
DECLARE @return_value int
declare @input_query nvarchar(max)
set @input_query = N'Select t1.*, t2.name from t1 t1 right join t2 t2 on
t1.id = t2.id where t1.date = ''period'' and t2.period between ''2016-01-01'' and ''2016-12-31'' and t2.def = ''u'''
EXEC @return_value = [dbo].[booksellers] @input_query
print 'query'
exec sp_executesql @input_query
SELECT 'Return Value' = @return_value
set @input_query = N'Select t1.*, t2.name from t1 t1 right join t2 t2 on
t1.id = t2.id where t1.date = ''period'' and t2.period between ''2017-01-01'' and ''2017-12-31'' and t2.def = ''u'''
EXEC @return_value = [dbo].[booksellers] @input_query
exec sp_executesql @input_query
SELECT 'Return Value' = @return_value
set @input_query = N'Select t1.*, t2.name from t1 t1 right join t2 t2 on
t1.id = t2.id where t1.date = ''period'' and t2.period between ''2017-01-01'' and ''2017-12-31'' and t2.def = ''x'''
EXEC @return_value = [dbo].[booksellers] @input_query
exec sp_executesql @input_query
SELECT 'Return Value' = @return_value
select 'Queued Queries', * from QueryData
declare @queries table (
queryId int,
rid int identity
)
insert into @queries ( queryId )
select rid from QueryData
declare @row int
declare @queryId int
declare @queryText nvarchar(max)
select @row = max(rid) from @queries
while @row > 0
begin
select @queryId = queryId from @queries where rid = @row
select @queryText = query from QueryData where rid = @queryId
select @queryText
exec sp_executesql @input_query
delete @queries where rid = @row
set @row = @row -1
end