代码之家  ›  专栏  ›  技术社区  ›  Orentet

如何将值的“数组”传递给存储过程?

  •  12
  • Orentet  · 技术社区  · 16 年前

    我希望能够将值的“数组”传递给存储过程,而不是串行调用“addvalue”过程。

    有人能建议一种方法吗?我是不是遗漏了什么?

    7 回复  |  直到 16 年前
        1
  •  9
  •   user80168 user80168    16 年前

    正如Chris所指出的,在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
    ];
    

    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)
    
        2
  •  5
  •   Kb.    16 年前

    如果您计划使用MySQL 5.1,则不可能传入数组。
    faq
    如果您计划使用PostgreSQL,您可以 here

        3
  •  3
  •   mu is too short    13 年前

    我不知道如何将实际数组传递到这些引擎中(我使用sqlserver),但这里有一个想法,可以通过此函数传递分隔字符串并在存储过程中对其进行解析。

    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  
    
        4
  •  2
  •   Mitch Wheat    16 年前

    here's one way .

    以及微软的支持 ref .

        5
  •  2
  •   a_m0d    13 年前

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

    然后简单地打电话 spTest_Array('1|2|3|4|5') 应生成与上述PostgreSQL查询相同的结果集。

        6
  •  1
  •   Kevin Barasa    7 年前

    多亏了MySQL中的JSON支持,您现在实际上能够将数组传递给MySQL存储过程。创建一个JSON_数组,并将其作为JSON参数传递给存储过程。 然后在这个过程中,使用MySQL的WHILE循环和MySQL的JSON“路径”,访问JSON_数组中的每个元素,并按照您的意愿进行操作。 这里有一个例子 https://gist.githubusercontent.com/jonathanvx/513066eea8cb5919b648b2453db47890/raw/22f33fdf64a2f292688edbc67392ba2ccf8da47c/json.sql

        7
  •  0
  •   MAbraham1    13 年前

    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.
    //: