Как использовать один параметр sql для представления входного массива - PullRequest
0 голосов
/ 29 февраля 2020

Есть ли способ написать sql для Oracle, MS SQL:

Select * from table where id in(:arr)


Select * from table where id in(@arr)

С одним параметром в sql 'arr' для представления массива элементов? Я нашел примеры, которые взрывают arr в @ arr0, .., @arrn и массив feed как n + 1 отдельных параметров, а не массив, как этот

Select * from table where id in(:arr0, :arr1, :arr2)


Select * from table where id in(@arr0, @arr1, @arr2)

Не то, что я хочу. Это приведет к изменению в запросе sql, и это создаст новые планы выполнения на основе номера параметра.

Я прошу. net, c# и Oracle и MS SQL.

Спасибо за конструктивные идеи!

/ ip /

Ответы [ 3 ]

0 голосов
/ 29 февраля 2020

Я считаю, что параметр Table Value является хорошим вариантом для этого случая. Посмотрите пример кода ниже на сервере SQL.

-- Your table
CREATE TABLE SampleTable
(
    ID          INT
)

INSERT INTO SampleTable VALUES
(1010),
(2010),       
(3010),
(4010),
(5010),      
(6010),      
(7010),      
(8030)
GO

-- Create a TABLE type in SQL database which you can fill from front-end code
CREATE TYPE ParameterTableType AS TABLE  
(
    ParameterID INT
    --, some other columns
)
GO

-- Create a stored proc using table type defined above
CREATE PROCEDURE ParameterArrayProcedure
(
    @ParameterTable AS ParameterTableType READONLY
)
AS
BEGIN

    SELECT
        S.*
    FROM SampleTable S
    INNER JOIN @ParameterTable P ON S.ID = P.ParameterID

END
GO

-- Populated table type variable
DECLARE @ParameterTable AS ParameterTableType
INSERT INTO @ParameterTable (ParameterID) VALUES (1010), (4010), (7010)

EXECUTE ParameterArrayProcedure @ParameterTable

DROP PROCEDURE ParameterArrayProcedure
DROP TYPE ParameterTableType
DROP TABLE SampleTable
GO

Помимо параметра табличного значения, вы также можете использовать Json или XML значений как SQL параметр, но да, это определенно изменит ваш план выполнения соответственно.

0 голосов
/ 29 февраля 2020

Oracle

На других языках (например, Java) вы можете передать коллекцию SQL в качестве параметра связывания и напрямую использовать ее в операторе SQL.

Однако C# не поддерживает передачу SQL коллекций и поддерживает только передачу OracleCollectionType.PLSQLAssociativeArray ( ссылка на документацию ), что является PL / SQL только тип данных и не может использоваться (напрямую) в SQL инструкциях.

Чтобы передать массив, вам нужно будет передать PLSQLAssociativeArray хранимой процедуре PL SQL и использовать ее для преобразования это в коллекцию SQL, которую вы можете использовать в операторе SQL. Пример процедуры преобразования из ассоциативного массива PL / SQL в коллекцию SQL:

CREATE TYPE IntList AS TABLE OF INTEGER
/

CREATE PACKAGE tools IS
  TYPE IntMap IS TABLE OF INTEGER INDEX BY BINARY_INTEGER;

  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList;
END;
/

CREATE PACKAGE BODY tools IS
  FUNCTION IntMapToList(
    i_map IntMap
  ) RETURN IntList
  IS
    o_list IntList := IntList();
    i      BINARY_INTEGER;
  BEGIN
    IF i_map IS NOT NULL THEN
      i := o_list.FIRST;
      WHILE i IS NOT NULL LOOP
        o_list.EXTEND;
        o_list( o_list.COUNT ) := i_map( i );
        i := i_map.NEXT( i );
      END LOOP;
    END IF;
    RETURN o_list;
  END;
END;
/
0 голосов
/ 29 февраля 2020

В дополнение к Табличному параметру , как упомянул Стив, есть несколько других доступных методов. Например, вы можете проанализировать строку с разделителями

Пример

Declare @arr varchar(50) = '10,20,35'

Select A.*
 From  YourTable A
 Join string_split(@arr,',') B on A.ID=value

Или даже

Select A.*
 From  YourTable A
 Where ID in ( select value from string_split(@arr,',') )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...