Como posso passar um "array" de valores para o meu procedimento armazenado?

votos
12

Eu quero ser capaz de passar um array de valores para o meu procedimento armazenado, em vez de chamar Adicionar valor procedimento de série.

Alguém pode sugerir uma maneira de fazê-lo? estou faltando alguma coisa aqui?

Edit: eu vou estar usando PostgreSQL / MySQL, eu não decidi ainda.

Publicado 01/01/2009 em 14:25
fonte usuário
Em outras línguas...                            


7 respostas

votos
2

Você não indicou, mas se você está se referindo ao servidor SQL, aqui está uma forma .

E a MS apoiar ref .

Respondeu 01/01/2009 em 14:39
fonte usuário

votos
4

Se você planeja usar o MySQL 5.1, não é possível passar em uma matriz.
Veja o MySQL 5.1 faq
Se você pretende usar o PostgreSQL, é possível olhar aqui

Respondeu 01/01/2009 em 15:56
fonte usuário

votos
2

Eu não sei sobre a passagem de um array real para esses motores (eu trabalho com sqlserver), mas aqui vai uma idéia para passar uma cadeia delimitada e analisá-lo em sua sproc com esta função.

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 IGNORE  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  
Respondeu 01/01/2009 em 16:07
fonte usuário

votos
1

Para PostgreSQL, você poderia fazer algo parecido com isto:

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;

Então, você poderia passar uma cadeia delimitada para o procedimento armazenado.

Digamos, parâmetro1 foi um parâmetro de entrada contendo '1|2|3|4|5'

A declaração:

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

resulta num conjunto de resultados que podem ser unidas ou inserido.

Da mesma forma, para o MySQL, você poderia fazer algo parecido com isto:

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 IGNORE  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 
$$

Em seguida, basta ligar spTest_Array('1|2|3|4|5')deve produzir o mesmo definido como a consulta PostgreSQL acima do resultado.

Respondeu 18/08/2009 em 07:43
fonte usuário

votos
9

Como Chris apontou, em PostgreSQL não é nenhum problema - qualquer tipo de base (como int, texto) tem a sua própria subtipo matriz, e você também pode criar tipos personalizados incluindo os compósitos. Por exemplo:

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

Agora você pode facilmente criar matriz de teste:

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

Você pode escrever uma função que irá multiplicar n * m para cada item na matriz, e retornar soma dos produtos:

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;

e executá-lo:

# SELECT test_test(
    ARRAY[
        row(1, 2)::test,
        row(3,4)::test,
        row(5,6)::test
    ]
);
 test_test
-----------
        44
(1 row)
Respondeu 18/08/2009 em 10:15
fonte usuário

votos
0

Aliás, aqui está como você gostaria de acrescentar a matriz para uma chamada de função (armazenado-proc):

CallableStatement proc = null;
List<Integer> faultcd_array = Arrays.asList(1003, 1234, 5678);
//conn - your connection manager
conn = DriverManager.getConnection(connection string here);
proc = conn.prepareCall("{ ? = call procedureName(?) }");
proc.registerOutParameter(1, Types.OTHER);
//This sets-up the array
Integer[] dataFaults = faultcd_array.toArray(new Integer[faultcd_array.size()]);
java.sql.Array sqlFaultsArray = conn.createArrayOf("int4", dataFaults);
proc.setArray(2, sqlFaultsArray);
//:
//add code to retrieve cursor, use the data.
//:
Respondeu 27/04/2012 em 22:56
fonte usuário

votos
0

Graças ao apoio JSON no MySQL agora você realmente tem a capacidade de passar um array para seu procedimento armazenado MySQL. Criar um JSON_ARRAY e simplesmente passá-lo como um argumento JSON para o procedimento armazenado. Em seguida, no procedimento, usando loop WHILE do MySQL e JSON do MySQL "pathing", acessar cada um dos elementos da JSON_ARRAY e fazer o que quiser. Um exemplo aqui https://gist.githubusercontent.com/jonathanvx/513066eea8cb5919b648b2453db47890/raw/22f33fdf64a2f292688edbc67392ba2ccf8da47c/json.sql

Respondeu 15/10/2017 em 09:02
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more