PL/SQL query IN comma deliminated string

前端 未结 10 2124
攒了一身酷
攒了一身酷 2021-01-02 04:46

I am developing an application in Oracle APEX. I have a string with user id\'s that is comma deliminated which looks like this,

45,4932,20,19
相关标签:
10条回答
  • 2021-01-02 05:25

    Solution from Tony Andrews works for me. The process should be added to "Page processing" >> "After submit">> "Processes".

    0 讨论(0)
  • 2021-01-02 05:27

    you will need to run this as dynamic SQL.

    create the entire string, then run it dynamically.

    0 讨论(0)
  • 2021-01-02 05:30

    A bind variable binds a value, in this case the string '45,4932,20,19'. You could use dynamic SQL and concatenation as suggested by Randy, but you would need to be very careful that the user is not able to modify this value, otherwise you have a SQL Injection issue.

    A safer route would be to put the IDs into an Apex collection in a PL/SQL process:

    declare
        array apex_application_global.vc_arr2;
    begin
        array := apex_util.string_to_table (:P5_USER_ID_LIST, ',');
        apex_collection.create_or_truncate_collection ('P5_ID_COLL');
        apex_collection.add_members ('P5_ID_COLL', array);
    end;
    

    Then change your query to:

    SELECT * FROM users u WHERE u.user_id IN 
    (SELECT c001 FROM apex_collections
     WHERE collection_name = 'P5_ID_COLL')
    
    0 讨论(0)
  • 2021-01-02 05:31

    I have faced this situation several times and here is what i've used:

    SELECT * 
      FROM users u 
     WHERE ','||to_char(:P5_USER_ID_LIST)||',' like '%,'||to_char(u.user_id)||',%'
    

    ive used the like operator but you must be a little carefull of one aspect here: your item P5_USER_ID_LIST must be ",45,4932,20,19," so that like will compare with an exact number "',45,'".

    When using it like this, the select will not mistake lets say : 5 with 15, 155, 55.

    Try it out and let me know how it goes;)

    Cheers , Alex

    0 讨论(0)
  • 2021-01-02 05:33

    An easier solution is to use instr:

    SELECT * FROM users u 
    WHERE instr(',' || :P5_USER_ID_LIST ||',' ,',' || u.user_id|| ',', 1) !=0;
    

    tricks:

    ',' || :P5_USER_ID_LIST ||','
    

    to make your string ,45,4932,20,19,

    ',' || u.user_id|| ','
    

    to have i.e. ,32, and avoid to select the 32 being in ,4932,

    0 讨论(0)
  • 2021-01-02 05:34

    Please dont use: WHERE ','||to_char(:P5_USER_ID_LIST)||',' like '%,'||to_char(u.user_id)||',%' because you'll force a full table scan although with the users table you may not have that many so the impact will be low but against other tables in an enterprise environment this is a problem.

    EDIT: I have put together a script to demonstrate the differences between the regex method and the wildcard like method. Not only is regex faster but it's also a lot more robust.

    -- Create table
    create table CSV_TEST
    (
      NUM NUMBER not null,
      STR VARCHAR2(20)
    );
    
    
    create sequence csv_test_seq;
    
    begin
      for j in 1..10 loop
        for i in 1..500000 loop
         insert into csv_test( num, str ) values ( csv_test_seq.nextval, to_char( csv_test_seq.nextval ));
        end loop;
        commit;
      end loop;
    end;
    /
    
    -- Create/Recreate primary, unique and foreign key constraints 
    alter table CSV_TEST
      add constraint CSV_TEST_PK primary key (NUM)
      using index ;
    alter table CSV_TEST
      add constraint CSV_TEST_FK unique (STR)
      using index;
    
    select sysdate from dual;
    select *
    from csv_test t
    where t.num in ( Select Regexp_Substr('100001, 100002,   100003   ,      100004, 100005','[^,]+', 1, Level) From Dual
                     Connect By Regexp_Substr('100001, 100002,100003, 100004, 100005', '[^,]+', 1, Level) Is Not Null);
    select sysdate from dual;
    
    select *
    from csv_test t
    where ('%,' || '100001,100002,   100003,  100004  ,100005' || ',%') like '%,' || num || ',%';
    select sysdate from dual;
    select *
    from csv_test t
    where t.num in ( Select Regexp_Substr('100001, 100002,   100003   ,      100004, 100005','[^,]+', 1, Level) From Dual
                     Connect By Regexp_Substr('100001, 100002,100003, 100004, 100005', '[^,]+', 1, Level) Is Not Null);
    select sysdate from dual;
    
    select *
    from csv_test t
    where ('%,' || '100001,100002,   100003,  100004  ,100005' || ',%') like '%,' || num || ',%';
    select sysdate from dual;
    
    drop table csv_test;
    drop sequence csv_test_seq;
    
    0 讨论(0)
提交回复
热议问题