Использование переменной в предложении IN в SQL Server 2017 - PullRequest
0 голосов
/ 28 сентября 2018

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

Сначала указан мой код, затем найдены ошибки.

Мой код:

DECLARE @OwnerSysID varchar(500)
SET @OwnerSysID = '3, 3476, 3511'

DECLARE @sql nvarchar(4000)
SET @sql = 'Select AllPosiable.UserID, AllPosiable.AgentSysID, 0' + 
            'From (' +
                'Select AgentSysID, UserID' + 
                'From (' +
                    'Select AGT_Agent.AgentSysID' +
                    'From AGT_Agent' +
                    'Where OwnerSysID IN ('+@OwnerSysID+')' +
                    'AND AgentName NOT LIKE %Texas State Low Cost%' +
                    'AND AgentName NOT LIKE %TSLC%' +
                    ') as AgentIDs ' +
                'Full Join (' +
                    'Select DISTINCT IW_UserAgentRelationship.UserID' +
                    'From AGT_Agent' +
                    'Left Join IW_UserAgentRelationship' +
                    'On IW_UserAgentRelationship.AgentID = AGT_Agent.AgentSysID' +
                    'Where OwnerSysID IN ('+@OwnerSysID+')' +
                    'And IW_UserAgentRelationship.isDefault = 1' +
                    'AND AgentName NOT LIKE %Texas State Low Cost%' + 
                    'AND AgentName NOT LIKE %TSLC%' +
                ') As UserIDs On 1=1' +
            ') as AllPosiable' +
            'Left Join IW_UserAgentRelationship' +
            'On IW_UserAgentRelationship.AgentID = AllPosiable.AgentSysID' +
            'And IW_UserAgentRelationship.UserID = AllPosiable.UserID' +
            'Where IW_UserAgentRelationship.AgentID Is NULL' 

EXEC sp_executesql @sql;

Ошибки:

Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'Select'.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'OwnerSysID'.
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'Join'.

Спасибо.

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

У вас есть несколько проблем в вашем запросе.Попробуйте это:

SET @sql = N'  -- strings should nvarchar for sp_executesql
Select AllPosiable.UserID, AllPosiable.AgentSysID, 0
From (Select AgentSysID, UserID
      From (Select AGT_Agent.AgentSysID
            From AGT_Agent
            Where OwnerSysID IN (@OwnerSysID) and
                  AgentName NOT LIKE ''%Texas State Low Cost%'' and
                  AgentName NOT LIKE ''%TSLC%''
           ) AgentIDs Full Join
           (Select DISTINCT IW_UserAgentRelationship.UserID
            From AGT_Agent Left Join
                 IW_UserAgentRelationship
                 On IW_UserAgentRelationship.AgentID = AGT_Agent.AgentSysID
            Where OwnerSysID IN (@OwnerSysID) and
                  IW_UserAgentRelationship.isDefault = 1 and
                  AgentName NOT LIKE ''%Texas State Low Cost%'' and
                  AgentName NOT LIKE ''%TSLC%''
           ) UserIDs
           On 1 = 1
      ) AllPosiable Left Join
      IW_UserAgentRelationship
      On IW_UserAgentRelationship.AgentID = AllPosiable.AgentSysID and
         IW_UserAgentRelationship.UserID = AllPosiable.UserID
Where IW_UserAgentRelationship.AgentID Is NULL
' ;

SET @sql = replace(@sql, n'@OwnerSysID', @OwnerSysID)

EXEC sp_executesql @sql;

Ваша основная проблема - не понимание того, что строка может занимать несколько строк в SQL Server.Это означает, что вам не нужно объединять кучу разных строк вместе.В вашем случае вы объединяете ключевые слова, поэтому SQL не понятен.Если бы вы распечатали @sql, это было бы очевидно.

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

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

0 голосов
/ 28 сентября 2018

Я предполагаю, что вы выбираете динамический SQL-маршрут только потому, что вам нужно передать @OwnerSysID в виде значений, разделенных запятыми, чтобы поместить его в IN()

, если это так, тогда используйтеTVF для передачи переменной с разделенными запятыми значениями без использования динамического sql.

Я упоминал этот метод в этом посте

По сути, вам нужна функция Table Valued, которая будет обрабатывать @OwnerSysID для преобразования своих значений в строки (сс помощью техники XML), затем используйте ее внутри IN()

Необходимая функция:

CREATE FUNCTION Split(@String VARCHAR(MAX))
RETURNS TABLE 
AS
RETURN 
(
    SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) MyString
    FROM (
        SELECT CAST('<XMLRoot><RowData>' + REPLACE(@String,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) MyString
    ) D
    CROSS APPLY MyString.nodes('/XMLRoot/RowData')m(n)
)

, затем вы можете использовать ее в своем запросе следующим образом:

OwnerSysID IN (SELECT * FROM dbo.Split(@OwnerSysID))

При использовании этого метода вам не нужен динамический sql, достаточно обычного запроса.

0 голосов
/ 28 сентября 2018

Это не передает переменную в предложение IN ().Это прямая конкатенация строк, уязвимая для инъекций, поэтому будьте очень осторожны в том, как вы ее используете.

Но проблема здесь:

SET @sql = 'Select AllPosiable.UserID, AllPosiable.AgentSysID, 0' + 
            'From (' +

В пробеле нет пробеловстрока после 0 в конце первой строки, без пробела перед словом From в начале второй строки, и разрыв строки между ними не является частью результирующей строки ,Вы получите следующее:

Select AllPosiable.UserID, AllPosiable.AgentSysID, 0From (...

Попробуйте:

SET @sql = 'Select AllPosiable.UserID, AllPosiable.AgentSysID, 0' + 
            ' From (' +

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

Кроме того, вынужно посмотреть на этот отрывок:

'AND AgentName NOT LIKE %Texas State Low Cost%' +

Выражение %Texas State Low Cost% не будет частью строкового литерала в результирующем коде SQL.Вам нужно сделать это:

 'AND AgentName NOT LIKE ''%Texas State Low Cost%''' +

и, опять же, убедиться, что все строковые литералы в операторе SQL обрабатываются одинаково.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...