【问题标题】:PL/SQL Iterate through Select result - connect results to returnable typePL/SQL 遍历选择结果 - 将结果连接到可返回类型
【发布时间】:2021-03-02 22:42:36
【问题描述】:

我在一个过程中有这个循环:

FOR foundU IN (SELECT id, uName FROM USERS)
LOOP
-- do something--
END LOOP;

我的目标是将 Select-Statement 中找到的每个用户(id 和 uName)添加到循环内这些用户的可返回“列表”中。循环完成后,我想返回结果,因此我可以在 Java 中使用它(通过 CallableStatement)。我知道 SQL 中没有列表,我猜游标应该能够做到这一点,但我就是不知道该怎么做。

如果我很难理解我想说什么,也许我的循环中的这个 sn-p 可以更好地解释:

FOR foundU IN (SELECT id, uName FROM USERS)
    LOOP
    -- ListofFoundUsers.add(foundU.id, foundU.uName);
    END LOOP;
 -- return ListofFoundUsers;

【问题讨论】:

    标签: sql loops plsql cursor oracle-sqldeveloper


    【解决方案1】:

    您可以通过两种方式做到这一点。

    光标

    此方法从 PL/SQL 返回一个游标,我们将其转换(强制转换)为 ResultSet,然后像往常一样迭代。您会注意到我使用了 OracleTypes.CURSOR,这使得它特定于 Oracle JDBC 驱动程序。

    PL/SQL

    CREATE OR REPLACE PROCEDURE ret_sys_refcursor(o_cursor OUT SYS_REFCURSOR) IS
    BEGIN
      OPEN o_cursor FOR
        SELECT o.object_name
          FROM all_objects o
         WHERE o.owner = 'SYS'
           AND rownum < 10;
    END ret_sys_refcursor;
    /
    

    Java

    import java.io.IOException;
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    import oracle.jdbc.OracleTypes;
    
    public class so64913833 {
        public static void main(String[] args)
                throws ClassNotFoundException, SQLException, IOException {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            List<String> objects = new ArrayList<String>();
    
            try (Connection connection = DriverManager.getConnection(
                    "jdbc:oracle:thin:@//<db.host.name:port/sid>", "<user>",
                    "<password>")) {
    
                try (CallableStatement cs = connection
                        .prepareCall("{  call ret_sys_refcursor(?) }")) {
    
                    cs.registerOutParameter(1, OracleTypes.CURSOR);
                    cs.execute();
    
                    try (ResultSet rs = (ResultSet) cs.getObject(1)) {
                        while (rs.next()) {
                            objects.add(rs.getString("OBJECT_NAME"));
                        }
                    }
                }
            }
    
            for (String object : objects) {
                System.out.println(object);
            }
        }
    }
    

    打印:

    .xdk_version_10.2.0.3.0_production
    .xdk_version_10.2.0.5.0_production
    .xdk_version_11.2.0.3.0_production
    .xdk_version_12.2.0.1.0_production
    ACCESS$
    ACLMV$
    ACLMV$_BASE_VIEW
    ACLMV$_MVINFO
    ACLMV$_REFLOG
    

    收藏

    此方法使用自定义数据库类型。它的局限性在于需要一种与每个可能的记录结构相匹配的类型,但是对于字符串或数字的基本列表,您可以将它们设为通用。这在here 中有大量记录。您会注意到此示例不需要使用 OracleTypes。

    PL/SQL

    CREATE OR REPLACE TYPE t_string_tab AS TABLE OF VARCHAR2(4000);
    
    CREATE OR REPLACE PROCEDURE ret_string_tab(o_string_tab OUT t_string_tab) IS
    BEGIN
      SELECT o.object_name
        BULK COLLECT
        INTO o_string_tab
        FROM all_objects o
       WHERE o.owner = 'SYS'
         AND rownum < 10;
    END ret_string_tab;
    /
    

    Java

    import java.io.IOException;
    import java.sql.CallableStatement;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Types;
    import java.util.Arrays;
    import java.util.List;
    
    public class so64913833 {
        public static void main(String[] args)
                throws ClassNotFoundException, SQLException, IOException {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            List<String> objects = null;
    
            try (Connection connection = DriverManager.getConnection(
                    "jdbc:oracle:thin:@//<db.host.name:port/sid>", "<user>",
                    "<password>")) {
    
                try (CallableStatement cs = connection
                        .prepareCall("{  call ret_string_tab(?) }")) {
    
                    cs.registerOutParameter(1, Types.ARRAY, "T_STRING_TAB");
                    cs.execute();
                    objects = Arrays.asList((String[]) cs.getArray(1).getArray());
                }
            }
    
            for (String object : objects) {
                System.out.println(object);
            }
        }
    }
    

    打印:

    .xdk_version_10.2.0.3.0_production
    .xdk_version_10.2.0.5.0_production
    .xdk_version_11.2.0.3.0_production
    .xdk_version_12.2.0.1.0_production
    ACCESS$
    ACLMV$
    ACLMV$_BASE_VIEW
    ACLMV$_MVINFO
    ACLMV$_REFLOG
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多