Ошибка в динамическом SQL

#sql #sql-server #sql-server-2008 #dynamic #dynamic-sql

#sql #sql-сервер #sql-server-2008 #динамический #dynamic-sql

Вопрос:

Я создал следующий SP для генерации инструкций Update, и он использует таблицу Col .TMap.T_Mp и данные в таблице выглядят следующим образом:

 ID  M_Type  ID_F     SF1      SF2
1   Acc     ACC_ID   AC_ID    NULL
1   STA     STA_ID   ST_ID    NULL
1   CHa     Cha_ID   CH_ID    NULL



CREATE PROCEDURE dbo.dtmap(
@ID INT
)
AS
BEGIN

DECLARE @SQL NVARCHAR(MAX)
DECLARE @SchemaName SYSNAME
DECLARE @TableName SYSNAME
DECLARE @DatabaseName SYSNAME
DECLARE @M_Type SYSNAME
DECLARE @SF1 VARCHAR(50)
DECLARE @SF2 VARCHAR(50)
DECLARE @ID_F VARCHAR(50)
DECLARE @BR CHAR(2)
SET @BR = CHAR(13)   CHAR(10)


DECLARE tickmapcur CURSOR FOR SELECT M_Type,ID_F,SF1,SF2
                              FROM Col.TMap.T_Mp
                              WHERE   [_ID] = @ID 



SELECT  @SchemaName = Source_Schema ,
        @TableName = Source_Table ,
        @DatabaseName = Source_Database
FROM    Manserv.dbo.S_Ds
WHERE   ID = @ID



OPEN   tickmapcur  

FETCH NEXT FROM tickmapcur INTO @M_Type,@ID_F,@SF1,@SF2

while @@fetch_status = 0

BEGIN


SET @SQL = 'SELECT SO1,
                   SO2,
                   ID
INTO '   @M_Type   '_mtemp'   @BR   'FROM '   @M_Type   @BR
      'WHERE [ID] = '   CAST(@ID AS NVARCHAR(10))   @BR  @BR


SET @SQL = @SQL   'UPDATE  mt '   @BR   'SET '   @ID_F  ' = ac.'   @ID_F
      @BR   'FROM '   @DatabaseName   '.'   @SchemaName   '.'   @TableName   ' t'   @BR 
      'LEFT OUTER JOIN '  @M_Type   '_mtemp' 
     ' mtemp ON mtemp.ID = '    CAST(@ID AS NVARCHAR(10))   @BR 
       'INNER JOIN '   @M_Type   ' ac ON t.'   @SF1
      COALESCE(mtemp.SO1, '')   ' SV1'
      CASE WHEN @SF2 is NULL THEN '' ELSE COALESCE(@SF2, '')
      COALESCE(mtemp.SO2, '')   ' SV2' END
      'AND ac.[ID] = '   CAST(@ID AS NVARCHAR(10))
      @BR   'INNER JOIN '   @DatabaseName   '.'   @SchemaName   '.'
      @TableName   '_Dmtemp mt'   @BR
      'ON mt.[SRID] = t.[RID]  '   @BR
     @BR

FETCH NEXT FROM tickmapcur INTO @M_Type,@ID_F,@SF1,@SF2

PRINT ( @SQL )
END 

CLOSE tickmapcur
DEALLOCATE tickmapcur

END            
  

Я получаю следующее сообщение:

 Msg 4104, Level 16, State 1, Procedure dtmap, Line 57
The multi-part identifier "mtemp.SO1" could not be bound.
Msg 4104, Level 16, State 1, Procedure  dtmap, Line 57
The multi-part identifier "mtemp.SO1" could not be bound.
  

Вывод должен быть таким:

 SELECT SO1,
       SO2,
       ID
INTO  ACC_Mtemp
FROM ACC
WHERE [ID] = @ID



UPDATE  mt 
SET ACC_ID = ac.ACC_ID
FROM Ms.AT.AT_CRAW t
LEFT OUTER JOIN ACC_Mtemp mtemp ON
mtemp.ID = @ID
INNER JOIN Acc ac ON t.AC_ID=SV1
AND ac.ID = 1
INNER JOIN Ms.AT.AT_CRAW_Dmtemp mt  mt
ON mt.[SRID] = t.[RID]

SELECT SO1,
       SO2,
       ID
INTO  STA_Mtemp
FROM STA
WHERE [ID] = @ID



UPDATE  mt 
SET STA_ID = ac.STA_ID
FROM Ms.AT.AT_CRAW t
LEFT OUTER JOIN STA_Mtemp mtemp ON
mtemp.ID = @ID
INNER JOIN STA ac ON t.ST_ID=SV1
AND ac.ID = 1
INNER JOIN Ms.AT.AT_CRAW_Dmtemp mt  mt
ON mt.[SRID] = t.[RID]


SELECT SO1,
       SO2,
       ID
INTO  CHa_Mtemp
FROM CHa
WHERE [ID] = @ID



UPDATE  mt 
SET CHa_ID = ac.CHa_ID
FROM Ms.AT.AT_CRAW t
LEFT OUTER JOIN CHa_Mtemp mtemp ON
mtemp.ID = @ID
INNER JOIN CHa ac ON t.CH_ID=SV1
AND ac.ID = 1
INNER JOIN Ms.AT.AT_CRAW_Dmtemp mt  mt
ON mt.[SRID] = t.[RID]
  

Комментарии:

1. Можете ли вы показать нам результат этого PRINT ( @SQL ) ?

2. @Joe Я добавил выходные данные к своему вопросу

Ответ №1:

Вы неправильно формируете запрос. ВСЕ части SQL должны быть в кавычках. Единственной вещью вне них должны быть переменные, которые вы передаете.

Комментарии:

1. @Chris Я знаю, что проблема в том, что временная таблица создается динамически, где as COALESCE (mtemp.SO1, «) — это обычный SQL, и он пытается получить значение этого столбца из этой временной таблицы, которая создается динамически. Но я не знаю, как это исправить

2. @Sam: Нет, проблема в том, что вы смешали обычный SQL (COALESCE(mtemp.SO1, «) ВНЕ вашей конкатенации строк. Единственной вещью вне кавычек должны быть добавляемые переменные.

3. @Chris Я не могу использовать их в строке, поскольку mtemp.SO1 и mtemp.SO2 имеют значения типа ‘=’, ‘Like’, и я буду использовать их в соединении, поэтому я не могу поместить их в строку

4. @Sam — если быть более конкретным, проблема в том, что вы подходите к этой проблеме таким образом, который НИКОГДА НЕ БУДЕТ РАБОТАТЬ. Вы не можете создать динамическую строку на основе результатов внутри строки. Потенциально вы могли бы создать динамический запрос для создания другого вложенного динамического запроса, но это довольно плохая идея.

5. @Sam — Возможно, переосмыслите свой процесс. Возможно, создайте новый пост, содержащий предложения по вашей структуре данных, образцам данных и тому, чего вы пытаетесь достичь.

Ответ №2:

Вы не можете использовать mtemp псевдоним при создании строки. Я полагаю, что вы хотите использовать это в запросе вместо:

   ' COALESCE(mtemp.SO1, '''') SV1'
  

То же самое для mtemp.SO2 двух строк ниже.

Комментарии:

1. Я знаю, что проблема в том, что временная таблица создается динамически, где as COALESCE (mtemp.SO1, «) — это обычный SQL, и он пытается получить значение этого столбца из этой временной таблицы, которая создается динамически. Но я не знаю, как это исправить

2. @Sam: В этом случае вам нужно создать временную таблицу, прежде чем вы сможете создать вторую часть динамического запроса, поэтому ваш динамический запрос должен был бы создать динамический запрос.

Ответ №3:

Похоже, у вас отсутствует одинарная кавычка перед COALESCE(mtemp.SO1, '') разделом.

Комментарии:

1. Я знаю, что проблема в том, что временная таблица создается динамически, где as COALESCE (mtemp.SO1, «) — это обычный SQL, и он пытается получить значение этого столбца из этой временной таблицы, которая создается динамически. Но я не знаю, как это исправить