Использование параметра SQL, где требуется строковый литерал - PullRequest
0 голосов
/ 08 июня 2019

Я пытаюсь превратить верхний код верхнего решения из здесь в пользовательскую функцию SQL.Однако, когда я пытаюсь использовать переменную для числа 4 (в первом аргументе функции-значения), это barfs.

Так что это работает:

SELECT CAST('<x>' + REPLACE(@Input,',','</x><x>') + '</x>' AS XML).value('/x[4]','int')

... новсякий раз, когда я пытаюсь заменить '/ x [4]', чтобы использовать переменную вместо 4, я получаю сообщение вроде

Аргумент 1 метода типа данных XML "значение" долженбыть строковым литералом.

Вот моя полная пользовательская функция на данный момент ... просто учусь:

USE [DBName]
GO

CREATE FUNCTION fx_SegmentN
    (@Input AS VARCHAR(100),
     @Number AS VARCHAR(1)) 
RETURNS varchar(100)
AS
BEGIN
    DECLARE @ValueStringLiteral varchar(14)
    SET @ValueStringLiteral = '/x[' + @Number + ']'

    RETURN '' + 
        CASE
            WHEN @Number <1
                THEN ('ERROR')
            WHEN @Number = 1
                THEN (LEFT(@Input, CHARINDEX('-', @Input, 1)-1))
            WHEN @Number > 1
                --THEN (SELECT CAST('<x>' + REPLACE(@Input,',','</x><x>') + '</x>' AS XML).value('/x[4]','int')) --THIS LINE WORKS
                THEN (SELECT CAST('<x>' + REPLACE(@Input,',','</x><x>') + '</x>' AS XML).value('/x[' + @Number + ']','int')) --THIS ONE DOES NOT
            ELSE
                (NULL)
        END + ''
END

Ответы [ 3 ]

1 голос
/ 08 июня 2019

Попробуйте это:

CREATE FUNCTION fx_SegmentN
    (
         @Input AS VARCHAR(100)
        ,@Number AS VARCHAR(1)
    ) RETURNS varchar(100)
    AS
BEGIN
    DECLARE @XML XML;
    DECLARE @value VARCHAR(100);

    SET @XML = CAST('<x>' + REPLACE(@Input,',','</x><x>') + '</x>' AS XML);

    WITH DataSource ([rowID], [rowValue]) AS
    (
        SELECT ROW_NUMBER() OVER (ORDER BY T.c ASC) 
              ,T.c.value('.', 'VARCHAR(100)')
        FROM @XML.nodes('./x') T(c)
    )
    SELECT @value = [rowValue]
    FROM DataSource
    WHERE [rowID] = @Number;

    RETURN @value;
END

GO

SELECT dbo.fx_SegmentN ('1a,2b,3c,4d,5e,6f,7g,8h', 3);

и вас может заинтересовать Сохраняет ли метод nodes() порядок документов?

0 голосов
/ 08 июня 2019

Это на самом деле довольно просто:

declare @x xml = N'
  <x>2345</x>
  <x>vsaaef</x>
  <x>fxcfs</x>
  <x>Number 4</x>
  <x>vxcv</x>
  <x>111</x>
';
declare @Position int = 4;

select t.c.value('./text()[1]', 'nvarchar(100)')
from @x.nodes('/x[position() = sql:variable("@Position")]') t(c);
0 голосов
/ 08 июня 2019

Это безобразный хак, но он работает:)

DECLARE @Query AS NVARCHAR(MAX) = N'SELECT CAST(''<x>'' + REPLACE(''' + @Input + ''' ,'','',''</x><x>'') + ''</x>'' AS XML).value(''/x['+ @Number + ']'',''int'')'
EXEC sp_executesql @Query
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...