Ответ 1
Если вы используете Sybase 12.5 или более ранние версии, вы не можете использовать функции. Обходной путь может заключаться в том, чтобы заполнить временную таблицу значениями и прочитать их оттуда.
Итак, у меня есть Sybase, хранимый proc, который принимает 1 параметр, который разделяет запятую список строк и запускает запрос с in в предложении IN():
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (@keyList)
Как мне вызвать мой сохраненный процесс с более чем 1 значением в списке? До сих пор я пробовал
exec getSomething 'John' -- works but only 1 value
exec getSomething 'John','Tom' -- doesn't work - expects two variables
exec getSomething "'John','Tom'" -- doesn't work - doesn't find anything
exec getSomething '"John","Tom"' -- doesn't work - doesn't find anything
exec getSomething '\'John\',\'Tom\'' -- doesn't work - syntax error
EDIT: Я действительно нашел эту страницу, которая имеет отличную ссылку на различные способы для pas массива sproc
Если вы используете Sybase 12.5 или более ранние версии, вы не можете использовать функции. Обходной путь может заключаться в том, чтобы заполнить временную таблицу значениями и прочитать их оттуда.
Это немного поздно, но у меня был этот точный вопрос некоторое время назад, и я нашел решение.
Трюк - это двойное цитирование, а затем завершение всей строки в кавычках.
exec getSomething """John"",""Tom"",""Bob"",""Harry"""
Измените свой proc, чтобы он соответствовал записи в таблице.
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE @keyList LIKE '%'+name+'%'
У меня это было в производстве с ASE 12.5; мы теперь на 15.0.3.
Передайте список, разделенный запятыми, в функцию, которая возвращает значение таблицы. Есть пример MS SQL где-то на StackOverflow, проклятый, если я могу увидеть его в данный момент.
CREATE PROCEDURE getSomething @keyList varchar(4096) AS SELECT * FROM mytbl WHERE name IN (fn_GetKeyList(@keyList))
Звонок с -
exec getSomething 'John,Tom,Foo,Bar'
Я предполагаю, что Sybase должна иметь возможность сделать что-то подобное?
Вам нужно использовать список, разделенный запятыми? Последние пару лет я принимал эту идею и передавал в XML файл. Функция openxml принимает строку и делает ее как xml, а затем, если вы создаете временную таблицу с данными, она запрашивается.
DECLARE @idoc int
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
<Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
<OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>
<OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
<Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
<OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>
</Order>
</Customer>
</ROOT>'
--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
-- Execute a SELECT statement that uses the OPENXML rowset provider.
SELECT *
FROM OPENXML (@idoc, '/ROOT/Customer',1)
WITH (CustomerID varchar(10),
ContactName varchar(20))
Что касается идеи Кевина о передаче параметра функции, которая разбивает текст на таблицу, вот моя реализация этой функции из нескольких лет назад. Работает с удовольствием.
Это быстрый и грязный метод, который может быть полезен:
select *
from mytbl
where "," + ltrim(rtrim(@keylist)) + "," like "%," + ltrim(rtrim(name)) + ",%"
Не уверен, что в ASE, но в SQL Anywhere функция sa_split_list возвращает таблицу из CSV. Он имеет необязательные аргументы для передачи другого разделителя (по умолчанию это запятая) и maxlength для каждого возвращаемого значения.
Проблема с такими вызовами: exec getSomething "John", "Tom" - это то, что он обрабатывает "John", "Tom" как единую строку, он будет соответствовать только записи в таблице, это "Джон", "Том".
Если вы не хотите использовать временную таблицу, как в ответе Павла, вы можете использовать динамический sql. (Предполагается v12 +)
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
declare @sql varchar(4096)
select @sql = "SELECT * FROM mytbl WHERE name IN (" + @keyList +")"
exec(@sql)
Вам нужно будет убедиться, что элементы в @keylist содержат кавычки вокруг них, даже если они являются одиночными значениями.
Это работает в SQL. Объявите в своей процедуре GetSomething переменную типа XML как таковой:
DECLARE @NameArray XML = NULL
В теле хранимой процедуры реализовано следующее:
SELECT * FROM MyTbl WHERE name IN (SELECT ParamValues.ID.value('.', 'VARCHAR (10)') FROM @NameArray.nodes('id') AS ParamValues (ID))
Внутри кода SQL, который вызывает SP, объявляет и инициализирует переменную XML перед вызовом хранимой процедуры:
DECLARE @NameArray XML
SET @NameArray = '<id> Name_1 </id> <id> Name_2 </id> <id> Name_3 </id> <id> Name_4 </id> '
Используя ваш пример, вызов хранимой процедуры будет выглядеть следующим образом:
EXEC GetSomething @NameArray
Я использовал этот метод раньше, и он отлично работает. Если вам нужен быстрый тест, скопируйте и вставьте следующий код в новый запрос и выполните:
DECLARE @IdArray XML
SET @IdArray = '<id> Name_1 </id> <id> Name_2 </id> <id> Name_3 </id> <id> Name_4 </id> '
SELECT ParamValues.ID.value('.', 'VARCHAR (10)') FROM @IdArray.nodes('id') AS ParamValues (ID)
Чтобы коснуться того, что @Abel предоставила, мне помогло:
Моя цель состояла в том, чтобы взять конечный пользователь, введенный из SSRS, и использовать его в моем предложении where как In (SELECT) Очевидно, @ICD_VALUE_RPT будет закомментирован в моем запросе Dataset.
DECLARE @ICD_VALUE_RPT VARCHAR(MAX) SET @ICD_VALUE_RPT = 'Value1, Value2'
DECLARE @ICD_VALUE_ARRAY XML SET @ICD_VALUE_ARRAY = CONCAT('<id>', REPLACE(REPLACE(@ICD_VALUE_RPT, ',', '</id>,<id>'),' ',''), '</id>')
то в моем WHERE
я добавил:
(PATS_WITH_PL_DIAGS.ICD10_CODE IN (SELECT ParamValues.ID.value('.','VARCHAR(MAX)') FROM @ICD_VALUE_ARRAY.nodes('id') AS ParamValues(ID))
OR PATS_WITH_PL_DIAGS.ICD9_CODE IN (SELECT ParamValues.ID.value('.','VARCHAR(MAX)') FROM @ICD_VALUE_ARRAY.nodes('id') AS ParamValues(ID))
)
Попробуйте этот путь. Его работы для меня.
@itemIds varchar(max)
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (SELECT Value FROM [Global_Split] (@itemIds,','))