2017-01-09 4 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 - Эрланд Соммарског] (http://www.sommarskog.se/dynamic_sql.html) – SqlZim

+0

Как общий принцип, если вы НЕОБХОДИМО использовать динамический SQL, не делайте этого, как будто вы делаете это здесь, или как McNets предложил в своем ответе (используя 'EXEC()', хотя McNets предложил неправильный ответ по другим причинам). Вместо этого используйте 'EXEC sp_executesql'. Это позволяет правильно параметризовать ваши запросы. Вот статья, описывающая, почему это [дурная привычка] (http: // sqlblog.ком/блоги/aaron_bertrand/Архив/2011/09/17/плохие-привычки к ножным с использованием-Exec-вместо-оф-уд-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

Я не могу правильно понять запрос. Предполагается, что вы хотите заменить строку '@id' от answer_query со значениями в переменной @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), которая использует случай заявление, чтобы вернуть ответы, основанные на вопрос идентификатора и одного параметра. Каждый случай выполняет другой запрос к другим таблицам в базе данных и выравнивает/объединяет результаты в строку csv.

Смежные вопросы