2017-01-09 142 views
0

我想(和失败)创建一个子查询动态查询。 我有一个问题表,其中每个问题的可能答案都需要从一个或多个其他表中动态创建。我在问题表中有一个varchar字段,我想动态地使用它来查询可能的答案。例如:动态查询动态子查询

问题表:

----------------------------------------------------------------------------- 
id | question   | answer_query 
----------------------------------------------------------------------------- 
1 | Can this be done? | SELECT field1 + ' ' + field2 answers FROM table1 a JOIN table2 b ON b.field1 = a.field2 WHERE b.id = '@id' 

然后,我希望有一个存储过程创建这样一个动态查询:

DECLARE @id int 
SET @id....... 
DECLARE @sql_query varchar(3000); 
SET @sql_query = 
    'SELECT q.id, q.question, (REPLACE(q.answer_query, ''@id'', @id)) 
    FROM Questions q 
    JOIN Other Table ON .... 
    WHERE .....'; 

EXECUTE(@sql_query); 

道歉穷人格式!

正在尝试做什么?


+0

我的第一反应是:不这样做。如果你打算做这样的事情,从这里开始:[动态SQL的诅咒和祝福 - Erland Sommarskog](http://www.sommarskog.se/dynamic_sql.html) – SqlZim

+0

作为一般原则,如果你需要使用动态SQL,不要这样做,就像你在这里做的那样,或者像McNets在他的回答中所建议的那样(使用'EXEC()',即使McNets为其他原因建议了一个不正确的答案)。改为使用'EXEC sp_executesql'。它允许正确地参数化您的查询。这篇文章描述了为什么它是[坏习惯](http:// sqlblog。COM /博客/ aaron_bertrand /存档/ 2011/09/17 /坏习惯,对开球使用-EXEC-INSTEAD-OF-SP-executesql.aspx)。 – ZLK

回答

0

试试这个:

DECLARE @id int 
SET @id....... 
DECLARE @sql_query varchar(3000); 
SET @sql_query = 
    'SELECT q.id, q.question, ' 
    + (REPLACE(q.answer_query, '@id', @id)) 
    + ' FROM Questions q 
    JOIN Other Table ON .... 
    WHERE .....'; 

EXECUTE(@sql_query); 
0

你想

SET @sql_query = (SELECT REPLACE(q.answer_query, '@id', @id) 
    FROM Questions q 
    JOIN Other Table ON .... 
    WHERE .....) 

SELECT @sql_query = REPLACE(q.answer_query, '@id', @id) 
FROM Questions q 
JOIN Other Table ON .... 
WHERE .....) 

然而,这似乎是有很多原因一个非常糟糕的主意。有没有其他办法可以解决这个问题。

例如 - 不要在表中使用select语句,而要尊重视图名称。这解决了很多问题,编译器可以优化你不打开sql注入 - 非常好。

0

我无法正确理解查询。假设您要将answer_query中的字符串'@id'替换为变量@id中的值。

如果是这样,请尝试以下查询:

DECLARE @id int 
SET @id=..... 
DECLARE @sql_query varchar(3000); 
SET @sql_query = 
    'SELECT q.id, q.question, (REPLACE(q.answer_query, ''@id'', '+CONVERT(VARCHAR(10),@id)+')) 
    FROM Questions q 
    JOIN Other Table ON .... 
    WHERE .....'; 
EXECUTE(@sql_query); 
0

感谢所有为您的意见。我提出了下面的解决方案,但并不像我想的那样通用。

Table structure

存储过程:

CREATE PROCEDURE [dbo].[spQuestionsByTypeAndOther] 
    @type_id uniqueidentifier, 
    @other_param_id uniqueidentifier 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT q.id, q.question, q.required, dbo.fnGetAnswers(q.id, @other_param_id) 
    FROM Questions q 
    JOIN QuestionsToTypes t on t.question_id = q.id 
    WHERE t.type_id = @type_id 
END 

和一个函数(fnGetAnswers),它使用case语句返回基于问题ID和一个其他参数的答案。每种情况下都会针对数据库中的其他表执行不同的查询,并将结果展平/连接成csv字符串。