How to load a large number of strings to match wit

2018-12-31 12:54发布

问题:

I am currently learning PL/SQL so i am still a newbie. Assume that you have a production database, which you connect to using Oracle SQL developer. You have ONLY READ privilges to that databases. Therefore you cannot create or edit any tables.

My question is, if i have a big list of IDs, which i have to join with a table in that database, how can i do that?

Obviously, I can load the IDs onto a temporary table and then do a join, but that would be really tedious as i have only READ privileges. Hardcoding the IDs is not an option also, because the list is too big.

And also note that, i know the concept of TEMPORARY tables. But unfortunately, i also don\'t have privileges to create those.

Is there any solution in SQL developer where i can load the list of IDs, to match with the table in the database?

回答1:

Use a collection

VARIABLE cursor REFCURSOR;

DECLARE
  your_collection SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
BEGIN
  your_collection.EXTEND( 10000 );

  FOR i IN 1 .. 10000 LOOP
    -- Populate the collection.
    your_collection(i) := DBMS_RANDOM.STRING( \'x\', 20 );
  END LOOP;

  OPEN :cursor FOR
  SELECT t.*
  FROM   your_table t
         INNER JOIN
         TABLE( your_collection ) c
         ON t.id = c.COLUMN_VALUE;
END;
/

PRINT cursor;

Or doing the same thing via java:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OraclePreparedStatement;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;

public class TestDatabase2 {
    public static void main(String args[]){
        try{
            Class.forName(\"oracle.jdbc.OracleDriver\");

            Connection con = DriverManager.getConnection(\"jdbc:oracle:thin:@localhost:1521:XE\",\"username\",\"password\");

            String[] ids = { \"1\", \"2\", \"3\" };

            ArrayDescriptor des = ArrayDescriptor.createDescriptor(\"SYS.ODCIVARCHAR2LIST\", con);

            PreparedStatement st = con.prepareStatement(\"SELECT t.* FROM your_table t INNER JOIN TABLE( :your_collection ) c ON t.id = c.COLUMN_VALUE\");

            // Passing an array to the procedure - 
            ((OraclePreparedStatement) st).setARRAYAtName( \"your_collection\", new ARRAY( des, con, ids ) );
            ResultSet cursor = st.executeQuery();

            while ( cursor.next() )
            {
                int id = cursor.getInt(1);
                double column1 = cursor.getDouble(2);
                double column2 = cursor.getDouble(3);

                System.out.println( String.format( \"Id: %5d\", id ) );
                System.out.println( String.format( \"  Column1: %s\", column1 ) );
                System.out.println( String.format( \"  Column2: %s\", column2 ) );
            }
        } catch(ClassNotFoundException | SQLException e) {
            System.out.println(e);
        }
    }
}


回答2:

You can try doing the search by constructing a query like this:

SELECT * FROM YourTable WHERE ID IN (Id1, Id2, ...., Idn)

This is limited to 1000 Ids, but it can be circumvented using this little trick shown here.



回答3:

Your friendly dba can map a directory for you to use, that will let you plop your file in there, and treat it as a table. Then basically you join with the file-as-table. Ask your DBA about EXTERNAL_TABLES.