答えは、アポストロフィをエスケープすることです。テキストを変数に割り当てたり、データベースに挿入したりする場合は、アポストロフィをエスケープする必要があります。
エスケープ処理は、プロセッサではなく、クエリパーサーによって処理されます。エスケープアポストロフィで挿入されたデータを参照するか、データベースから取得したデータを見ると、アポストロフィを1つ戻して取得します。あなたのデータには影響しません。
あなたが正しく理解している場合は、後でそのテーブルをクエリしてそれらのクエリを実行できるように、そのクエリをテーブルに挿入しています。いくつかの報告されている報告プログラムの痛みですか?
この概念証明クエリは、これが可能であることを証明します。あなたのスキーマがないので、テーブルの名前を変更する必要がありました。
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
あなたは何をしなければならないかを知っています。早くやれよ。文字列リテラルの一重引用符を二重にする必要があります。それ以外の方法はありません。 – Jeremy
これは、修正されるまで問題を引き起こす不良アーキテクチャの例です。何らかの理由で、コードでステートメントを生成するのが良いと思う場合は、コードからステートメントを実行するだけです。それをprocに渡して実行しないでください...何の意味もありません。コード内にあれば、アプリケーション開発者はエラーを受け取り、ステートメントが無効であるため、必要に応じてエラーを修正する必要があります。また、パラメータ化されておらず、怠け者であり、パフォーマンスが低下し、注入脆弱性につながります。これに関するすべてが間違っています。 – btberry
[SQL Serverのエスケープ文字]の重複している可能性があります(http://stackoverflow.com/questions/5139770/escape-character-in-sql-server) – serverSentinel