Как я могу передать “массив” значений к моей хранимой процедуре?

Вы можете найти дополнительную информацию о грани MSDN-модели данных сущностей. http://msdn.microsoft.com/en-us/library/ee382834.aspx Полностью рекомендуется.

14
задан Blair Conrad 1 January 2009 в 14:43
поделиться

5 ответов

Как указал Крис, в PostgreSQL это не проблема - любой базовый тип (например, int, text) имеет собственный подтип массива, и вы также можете создавать собственные типы, включая составные. Например:

CREATE TYPE test as (
    n int4,
    m int4
);

Теперь вы можете легко создать массив теста:

select ARRAY[
    row(1,2)::test,
    row(3,4)::test,
    row(5,6)::test
];

Вы можете написать функцию, которая будет умножать n * m для каждого элемента в массиве, возвращать сумму продуктов:

CREATE OR REPLACE FUNCTION test_test(IN work_array test[]) RETURNS INT4 as $$
DECLARE
    i      INT4;
    result INT4 := 0;
BEGIN
    FOR i IN SELECT generate_subscripts( work_array, 1 ) LOOP
        result := result + work_array[i].n * work_array[i].m;
    END LOOP;
    RETURN result;
END;
$$ language plpgsql;

и запускать ее:

# SELECT test_test(
    ARRAY[
        row(1, 2)::test,
        row(3,4)::test,
        row(5,6)::test
    ]
);
 test_test
-----------
        44
(1 row)
9
ответ дан 1 December 2019 в 13:22
поделиться

Если Вы планируете использовать MySQL 5.1, не возможно передать в массиве.
Видят часто задаваемые вопросы MySQL 5.1
, Если Вы планируете использовать PostgreSQL, это - возможный взгляд здесь

4
ответ дан 1 December 2019 в 13:22
поделиться

Я не знаю о передаче фактического массива в те механизмы (я работаю с sqlserver), но вот идея для передачи разграниченной строки и парсинга его в Вашем sproc с этой функцией.

CREATE FUNCTION [dbo].[Split]
(
    @ItemList NVARCHAR(4000), 
    @delimiter CHAR(1)
)
RETURNS @IDTable TABLE (Item VARCHAR(50))  
AS      

BEGIN    
    DECLARE @tempItemList NVARCHAR(4000)
    SET @tempItemList = @ItemList

    DECLARE @i INT    
    DECLARE @Item NVARCHAR(4000)

    SET @tempItemList = REPLACE (@tempItemList, ' ', '')
    SET @i = CHARINDEX(@delimiter, @tempItemList)

    WHILE (LEN(@tempItemList) > 0)
    BEGIN
        IF @i = 0
            SET @Item = @tempItemList
        ELSE
            SET @Item = LEFT(@tempItemList, @i - 1)
        INSERT INTO @IDTable(Item) VALUES(@Item)
        IF @i = 0
            SET @tempItemList = ''
        ELSE
            SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i)
        SET @i = CHARINDEX(@delimiter, @tempItemList)
    END 
    RETURN
END  
2
ответ дан 1 December 2019 в 13:22
поделиться

Вы не указали, но если Вы обращаетесь к SQL-серверу, вот один путь .

И поддержка MS касательно .

2
ответ дан 1 December 2019 в 13:22
поделиться

Для PostgreSQL вы можете сделать что-то вроде этого:

CREATE OR REPLACE FUNCTION fnExplode(in_array anyarray) RETURNS SETOF ANYELEMENT AS
$$
    SELECT ($1)[s] FROM generate_series(1,array_upper($1, 1)) AS s;
$$
LANGUAGE SQL IMMUTABLE;

Затем вы можете передать строку с разделителями в вашу хранимую процедуру.

Скажем, param1 был входным параметром, содержащим '1 | 2 | 3 | 4 | 5'

Оператор:

SELECT CAST(fnExplode(string_to_array(param1, '|')) AS INTEGER);

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

Аналогично, для MySQL вы можете сделать что-то вроде этого:

DELIMITER $$
CREATE PROCEDURE `spTest_Array`
(
    v_id_arr TEXT
)
BEGIN
    DECLARE v_cur_position INT; 
    DECLARE v_remainder TEXT; 
    DECLARE v_cur_string VARCHAR(255); 
    CREATE TEMPORARY TABLE tmp_test
    ( 
        id INT
    ) ENGINE=MEMORY; 

    SET v_remainder = v_id_arr; 
    SET v_cur_position = 1;

    WHILE CHAR_LENGTH(v_remainder) > 0 AND v_cur_position > 0 DO 
        SET v_cur_position = INSTR(v_remainder, '|'); 
        IF v_cur_position = 0 THEN 
            SET v_cur_string = v_remainder; 
        ELSE 
            SET v_cur_string = LEFT(v_remainder, v_cur_position - 1); 
        END IF; 

        IF TRIM(v_cur_string) != '' THEN 
            INSERT INTO tmp_test
                (id)
            VALUES 
                (v_cur_string);                 
        END IF; 

        SET v_remainder = SUBSTRING(v_remainder, v_cur_position + 1); 
    END WHILE; 

    SELECT 
        id
    FROM 
    tmp_test;

    DROP TEMPORARY TABLE tmp_test;
END 
$$

Затем просто CALL spTest_Array ('1 | 2 | 3 | 4 | 5') должен дать тот же набор результатов, что и указанный выше запрос PostgreSQL.

1
ответ дан 1 December 2019 в 13:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: