sql >> データベース >  >> RDS >> Mysql

Oracle:IN句を使用したパラメータ化されたクエリはnull値を返します

    カンマ区切りのリストをパラメーター(バインド変数)として渡すこともできますが、サブクエリで解析する必要があります。 このスレッド に基づくソリューション regexp_substrを使用します。

    CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHaR2, cur OUT sys_refcursor)
    AS
    BEGIN
    open cur for  'with t1 as (select :A col from dual),
         t2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
                  from t1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)
    select col as id from t2' using A;
    END;
    /
    

    手順は簡略化されていますが、使い方を理解できるはずです。

    動的SQL(文字列の連結)を使用することに対する大きな利点は、実行のたびにステートメントを解析する必要がないことです。セキュリティは言うまでもありません(SQLインジェクションの心配)。

    使用法:

    DECLARE 
      l_cur SYS_REFCURSOR;
      l_id NUMBER;
    BEGIN 
      p_getdata('1,1000,282828,4',l_cur);
     LOOP
        FETCH l_cur INTO l_id ;
        EXIT WHEN l_cur%NOTFOUND;
        dbms_output.put_line(l_id);
     END LOOP;
    END;
    /
    
    
    1
    1000
    282828
    4
    

    更新

    上記の手順は簡略化されています。機能を取得するには、CURSORでこのようなクエリを使用する必要があります(つまり、クエリに結果を適用するよりも、最初にサブクエリファクタリングを使用して3つのパラメータすべてを別々のサブクエリに分割します)

    CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHAR2, B in VARCHAR2, c in VARCHAR2, cur OUT sys_refcursor)
    AS
    BEGIN
    open cur for  'with ta1 as (select :A col from dual),
         ta2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
                  from ta1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
     tb1 as (select :B col from dual),
         tb2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
                  from tb1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
     tc1 as (select :C col from dual),
         tc2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
                  from tc1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)              
    select firstname, lastname, streetname, city
    from mytable 
    where zip IN (select col from ta2) AND 
          streetnumber IN (select col from tb2) AND 
          apt_num in (select col from tc2)' using A, B, C;
    END;
    /
    

    テストに合格しました

    DECLARE 
      l_cur SYS_REFCURSOR;
      l_firstname VARCHAR2(20);
      l_lastname VARCHAR2(20);
      l_streetname VARCHAR2(20);
      l_city VARCHAR2(20);
    BEGIN 
      p_getdata('1100,,1200','1,2','11,12' ,l_cur);
     LOOP
        FETCH l_cur INTO l_firstname, l_lastname, l_streetname, l_city;
        EXIT WHEN l_cur%NOTFOUND;
        dbms_output.put_line(l_firstname|| ' ' || l_lastname || ' ' || l_streetname  || ' ' || l_city);
     END LOOP;
    END;
    /
    


    1. ソケット'/tmp/mysql.sock'を介してローカルMySQLサーバーに接続できません(2)

    2. MySQLで通知用のデータベースを設計するためのガイド

    3. PHP定数が定義されていません

    4. あなたのビジネスのためのユーザーフレンドリーなデータベースを選択する方法