2015-01-17 2 views
1

Оставляя в стороне оговорки об использовании динамического SQL, мне интересно, могу ли я динамически объявлять, какую локальную переменную я хочу присвоить значение данной выходной переменной из динамического оператора SQL.Назначение динамических выходных переменных SQL для локальных переменных

Надеюсь, я сказал, что достаточно хорошо. Вот немного кода и где у меня проблемы. У меня есть хранимая процедура с рядом выходных параметров, например, так:

ALTER PROCEDURE [dbo].[mngi_psi_paginate] 

@image_desc_1   VARCHAR(50) OUTPUT 
,@image_desc_2   VARCHAR(50) OUTPUT 
,@image_desc_3   VARCHAR(50) OUTPUT 
,@image_desc_4   VARCHAR(50) OUTPUT 
,@image_desc_5   VARCHAR(50) OUTPUT 
,@image_desc_6   VARCHAR(50) OUTPUT 
,@image_desc_7   VARCHAR(50) OUTPUT 
,@image_desc_8   VARCHAR(50) OUTPUT 
,@image_desc_9   VARCHAR(50) OUTPUT 
,@image_desc_10   VARCHAR(50) OUTPUT 

...

Есть в общей сложности 40 выходных параметров. Я разрешаю пользователю просматривать неизвестное количество изображений, по 10 изображений за раз. Для каждого изображения мне нужны 4 поля данных, но с потенциалом по 10 записей за раз, я бы предпочел не кодировать все 40 назначений переменных.

Я понимаю, что должны быть лучшие способы сделать это, но получающее приложение не является веб-браузером, поэтому, к сожалению, это то, с чем мне нужно работать.

Я также делаю несколько других вещей: определите общее количество изображений, количество страниц и количество изображений, которые будут отображаться на странице.

Как только я выясню, какой набор изображений принадлежит данной странице, я помещаю их во временную таблицу.

CREATE TABLE #images_page 
    (primary_key INT IDENTITY(1,1) NOT NULL 
    ,image_id VARCHAR(36) 
    ,image_path VARCHAR(400) 
    ,image_type VARCHAR(5) 
    ,image_desc VARCHAR(MAX) 
    ) 

INSERT INTO  #images_page 
SELECT   image_id 
       ,image_path 
       ,image_type 
       ,image_desc 
FROM   @images_set 
WHERE   primary_key >= @image_start 
AND    primary_key <= @image_end 

Тогда я построить строку выполнить динамический оператор SQL, который все завернутый в цикле WHILE, с надеждой на возможность назначать только переменные, которые имеют соответствующую запись (например, @ image_desc_1 получает данные из строки # 1, @ image_desc_2 получает данные из строки # и т.д.

SELECT @image_page_total = COUNT(*) 
FROM #images_page 

DECLARE  @row_counter INT 
      ,@loop_counter INT 

SET @loop_counter = @image_page_total 
SET @row_counter = 1 

WHILE 
    @loop_counter > 0 
AND @row_counter <= @loop_counter 
BEGIN 

-- Dynamically assign variables 
DECLARE @sql  NVARCHAR(MAX) 
DECLARE @params  NVARCHAR(MAX) 
DECLARE @assign  NVARCHAR(MAX) 
SELECT @sql =  'SELECT @image_desc = image_desc ' + 
        '@image_path = image_path,' + 
        '@image_type = image_type,' + 
        '@image_comments = image_comments' + 
        'FROM #images_page ' + 
        'WHERE primary_key = ' + CAST(@row_counter AS VARCHAR) 

SELECT @params = '@image_desc varchar(50) OUTPUT' 
SELECT @assign = '@image_desc = @image_desc_' + CAST(@row_counter AS VARCHAR) + ' OUTPUT' 

--This line works because I've simply typed out the variable name 
EXEC sp_executesql @sql, @params, @image_desc = @image_desc_1 OUTPUT 
--This line does not work because I am trying to append the '_1' to @image_desc 
EXEC sp_executesql @sql, @params, @assign 

SET @row_counter = @row_counter + 1 

END 

Первый EXEC sp_executesql линия работает, потому что это так, как это должно работать, и это, как вы видите его во всей документации и примеры. Второй EXEC sp_executesql - это то, что я действительно хотел бы сделать, но я просто не могу понять, как это сделать.

Есть ли способ сделать это так, как я пытаюсь это сделать?

Я открыт для альтернативных методов, которые не требуют от меня жесткого кодирования назначений переменных.

Заранее благодарю за помощь!

ответ

2

Я не думаю, что вам нужно полностью, но, возможно, это поможет вам в правильном направлении. Он не полностью удаляет действие, чтобы ссылаться на все 40 переменных - это код, но вам не нужно жестко кодировать назначение переменной.

Я использовал свой собственный пример. Я устанавливаю значение @ T1 или @ T2 в зависимости от значения @I. Поэтому, если @I = 1, тогда @ T1 будет установлен на «SET AT RUNTIME». Если @I = 2, то для параметра @ T2 будет установлено значение «SET AT RUNTIME». Вам нужно будет передать все 40 переменных в ваш динамический запрос.

DECLARE @T1  INT, 
     @T2  INT, 
     @I  VARCHAR(10) = '2', 
     @SQL NVARCHAR(MAX); 

SET @SQL = 'SET @T' + @I + ' = ''SET AT RUNTIME''' 
EXEC sp_executesql @SQL, N'@T1 INT OUT, @T2 INT OUT', @T1 OUT, @T2 OUT 

SELECT @T1, @T2 

Надежда, что помогает

+0

Я боялся, что собирался быть ответом. Я вижу, что я могу динамически строить имя переменной в строке SQL, но на самом деле не имеет значения, не могу ли я ее динамически не передавать. Я сыграю с несколькими другими вариантами и дам вам знать, что я придумал. Я очень ценю ваш ответ на это. Живи долго и процветай! Я знаю - ты никогда не слышал этого раньше. Извините, я не мог удержаться. :-) –

+1

Что делать, если вы вернете его с заявлением об объединении? Тогда тот, который получил набор динамически, будет тем, который возвращается? – Spock

+0

Где я предлагаю? В третьем параметре sp_expectutesql или где-то еще? –

0

Кажется, что Спок правильно, и я не могу динамически вычислять переменную, которую я хочу передать из динамического SQL. Кто-то, пожалуйста, поправьте меня, если я ошибаюсь.

Поскольку у меня есть только 10 наборов переменных, с которыми приходится иметь дело, я сосал его и просто написал инструкцию IF для каждого из них. Опять же, если у кого-то есть лучшая альтернатива, я открыт для всего.

Для записи, вот что я сделал, и это работает:

SET @loop_counter = @image_page_total 
SET @row_counter = 1 

WHILE 
    @loop_counter > 0 
AND @row_counter <= @loop_counter 
BEGIN 

-- Dynamically assign variables 
DECLARE @sql  NVARCHAR(MAX) 
DECLARE @params  NVARCHAR(MAX) 
DECLARE @assign  NVARCHAR(MAX) 
SELECT @sql =  'SELECT @image_path = image_path, ' + 
        '@image_type = image_type, ' + 
        '@image_desc = image_desc, ' + 
        '@image_comments = image_comments ' + 
        'FROM #images_page ' + 
        'WHERE primary_key = ' + CAST(@row_counter AS VARCHAR) 

SELECT @params = '@image_path VARCHAR(400) OUTPUT, @image_type VARCHAR(5) OUTPUT, @image_desc VARCHAR(50) OUTPUT, @image_comments VARCHAR(MAX) OUTPUT' 

IF @row_counter = 1 EXEC sp_executesql @sql, @params, @image_type_1 OUTPUT, @image_type_1 OUTPUT, @image_desc_1 OUTPUT, @image_comments_1 OUTPUT 
IF @row_counter = 2 EXEC sp_executesql @sql, @params, @image_type_2 OUTPUT, @image_type_2 OUTPUT, @image_desc_2 OUTPUT, @image_comments_2 OUTPUT 
IF @row_counter = 3 EXEC sp_executesql @sql, @params, @image_type_3 OUTPUT, @image_type_3 OUTPUT, @image_desc_3 OUTPUT, @image_comments_3 OUTPUT 
IF @row_counter = 4 EXEC sp_executesql @sql, @params, @image_type_4 OUTPUT, @image_type_4 OUTPUT, @image_desc_4 OUTPUT, @image_comments_4 OUTPUT 
IF @row_counter = 5 EXEC sp_executesql @sql, @params, @image_type_5 OUTPUT, @image_type_5 OUTPUT, @image_desc_5 OUTPUT, @image_comments_5 OUTPUT 
IF @row_counter = 6 EXEC sp_executesql @sql, @params, @image_type_6 OUTPUT, @image_type_6 OUTPUT, @image_desc_6 OUTPUT, @image_comments_6 OUTPUT 
IF @row_counter = 7 EXEC sp_executesql @sql, @params, @image_type_7 OUTPUT, @image_type_7 OUTPUT, @image_desc_7 OUTPUT, @image_comments_7 OUTPUT 
IF @row_counter = 8 EXEC sp_executesql @sql, @params, @image_type_8 OUTPUT, @image_type_8 OUTPUT, @image_desc_8 OUTPUT, @image_comments_8 OUTPUT 
IF @row_counter = 9 EXEC sp_executesql @sql, @params, @image_type_9 OUTPUT, @image_type_9 OUTPUT, @image_desc_9 OUTPUT, @image_comments_9 OUTPUT 
IF @row_counter = 10 EXEC sp_executesql @sql, @params, @image_type_10 OUTPUT, @image_type_10 OUTPUT, @image_desc_10 OUTPUT, @image_comments_10 OUTPUT 

SET @row_counter = @row_counter + 1 

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