変数が選択リストにありません

このQ&Aのポイント
  • 変数が選択リストにありませんというエラーが出る理由について説明してください。
  • SELECT文とFETCHのINTOの変数の個数が一致していない場合にエラーが発生します。
  • 今回のコードでは、カーソルのFETCH時に変数の個数が一致していないため、エラーが出る可能性があります。
回答を見る
  • ベストアンサー

変数が選択リストにありません

変数が選択リストにありません 下記のコードを実行すると「変数が選択リストにありません」というエラーが出てしまいます。 SELECT文とFETCHのINTOの変数の個数が一致していない場合にこのエラーは出るということらしいのですが、問題ないように思うのです。 下記コードで何が問題になっているのか教えてください。 よろしくお願いします。 set serveroutput on; declare -- 各テーブルの全カラムを取得 cursor curcol (p_tblname user_tables.table_name%type) is select COLUMN_NAME,DATA_TYPE from user_tab_columns where table_name = p_tblname ; v_sql varchar2(1000); -- SQL文 v_col varchar2(1000); -- カラム名 v_val varchar2(1000); -- 取得データ v_tblname varchar2(20); -- テーブル名 v_RstExec integer; v_CursorID integer; begin v_col := ''; v_tblname := 'sample'; -- 取得テーブルのカラムを取得 for rowcol in curcol(v_tblname) loop -- 取得カラムをCSV形式に変換 if v_col is null then v_col := rowcol.COLUMN_NAME; else v_col := v_col||'||'',''||'||rowcol.COLUMN_NAME; end if; end loop; dbms_output.put_line(v_col); -- SQL作成 v_sql := 'select '||v_col||' from '||v_tblname; v_CursorID := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(v_CursorID, v_sql, DBMS_SQL.NATIVE); v_RstExec := DBMS_SQL.EXECUTE(v_CursorID); LOOP IF DBMS_SQL.FETCH_ROWS(v_CursorID) = 0 THEN EXIT; END IF; DBMS_SQL.COLUMN_VALUE(v_CursorID, 1, v_val); DBMS_OUTPUT.PUT_LINE(v_val); END LOOP; DBMS_SQL.CLOSE_CURSOR(v_CursorID); end; /

  • Oracle
  • 回答数4
  • ありがとう数7

質問者が選んだベストアンサー

  • ベストアンサー
  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.2

>DBMS_SQL.PARSE(v_CursorID, v_sql, DBMS_SQL.NATIVE); の後に DBMS_SQL.DEFINE_COLUMN( v_CursorID, 1, v_val,1000) ; が必要では?

shaka001
質問者

お礼

回答ありがとうございます。 DBMS_SQL.DEFINE_COLUMN( v_CursorID, 1, v_val,1000) ; 追加したらエラーが出なくなりました。 ただ、テーブル内の全レコードが表示されるかと思ったのですが1件しか表示されません。

その他の回答 (3)

  • SaKaKashi
  • ベストアンサー率24% (755/3136)
回答No.4

マニュアル http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19245-02/d_sql.htm#BABDJEBE によると2/の方のようにDEFINE_COLUMNが必要のようですけど。

shaka001
質問者

お礼

回答ありがとうございます。 declare部分だけに宣言すればいいのかと思っていました。

  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.3

#2です。連続ですみません。 user_tab_columnsのtable_nameには大文字で格納されているはずなので、 'sample'ではなく'SAMPLE'とするべきではないでしょうか。 まぁ、'sample'のままだったら >DBMS_SQL.PARSE( の時点でエラーになるでしょうから修正済みなのかもしれませんが。

shaka001
質問者

お礼

ご指摘ありがとうございます。 ご指摘のとおり、サンプルコードのためテーブル名を小文字にしてしまいましたが、実際のソースでは大文字にしてあります。

  • SaKaKashi
  • ベストアンサー率24% (755/3136)
回答No.1

v_colとv_sqlはどうなってますか?

shaka001
質問者

お礼

回答ありがとうございます。 v_colが sample_id||','||sample_name v_sqlが select sample_id||','||sample_name from sample v_sqlの値をコピペして単独で実行しても問題ありませんでした。

関連するQ&A

  • PL/SQLの動的SQLで複数の項目を取得する方法教えて下さい。

    動的SQLで複数の項目を取得する方法で 悩んでいます。 下記の例だと、1項目しか取れません。 何か他のやり方でもいいので、複数の項目を 取得する方法を教えていただきたいです。 ********************************************* declare sql_stmt varchar2(200); wk_grp varchar2(5); wk_name varchar2(30); type cursor_type is ref cursor; cur_name cursor_type; begin wk_grp := '1u'; open cur_name for 'select 名前 from 社員表 where 所属グループ = :v1' using wk_grp; loop fetch cur_name into wk_name; exit when cur_name%notfound; dbms_output.put_line(wk_name); end loop; close cur_name; end; ********************************************* 下記のようなDBMS_SQLパッケージ?? を利用した方法がいいんでしょうかね。。。。 DBMS_SQL.COLUMN_VALUE(SQL,1,WK_NAME) DBMS_SQL.COLUMN_VALUE(SQL,2,WK_NO) よくわかってないので、宜しくお願いします。

  • PRO*Cでテーブル名にバインド変数は使えますか?

    PRO*Cのプログラムで、テーブル名とカラム名をパラメータで 受け取って、ホスト変数(バインド変数?)に代入して、 それぞれ、SELECT文等で使用できますか? PL/SQLなら出来るでしょうか? EXEC SQL BEGIN DECLARE SECTION; varchar t_name[64]; /* テーブル名 */ varchar col_name[64]; /* カラム名 */ EXEC SQL END DECLARE SECTION; /* 中略 パラメータの値をホスト変数に代入する処理を行う */ ↓以下のように出来ますか? SELECT :col_name FROM :t_name ;

  • PLSQLのバインド変数の件です。

    こんにちわ。 いま,VBからテーブル名と列名をバインド変数としてPLSQLに渡しました。 そこで,PLSQLのなかで, v_Sql := 'UPDATE :Table_Name SET :Column_Name = :After_Change_Value WHERE :Column_Name = :Before_Change_Value ' ; のようにSQLを組み立て, DBMS_SQL.PARSE(v_Cursor, v_Sql, DBMS_SQL.NATIVE); でSQLを解析したところ,ERR-903となってしまいます。 ちなみに,:Table_Nameと:Column_Nameにテーブル名と列名をそのまま記述したところ,上記のエラーはパスできます。 VBからPLSQLにテーブル名と列名を変数として渡して,PLSQLのなかでSQLを解釈するにはどうすれば良いでしょうか? 教えてください。 宜しくお願いします。

  • PL/SQLでテーブル名に変数を使いたい

    下記のようにV_TABLE_NAMEに不定のテーブル名で使用したい ご存知の方は教えて頂けないでしょうか?V_TABLE_NAMEに取得したテーブルをセットし、データの件数を取得するPL/SQL CURSOR C_CUR IS SELECT COUNT (*) FROM V_TABLE_NAME; BEGIN for ・・・・・ loop ・・・  ・・・ V_TABLE_NAME := GET_TABLE;  OPEN C_CUR;  FETCH C_CUR into w_count; CLOSE C_CUR; end loop;

  • バインド変数について

    PL/SQLのバインド変数について調べていますが理解できず困っています。 [理解内容] 1.利点  :SQL文の検索にバインド変数を利用すると、同一のSQLとして実行できる   ⇒ 繰り返し処理(ループ)では有効 2.使用方法  :静的SQL・動的SQLで使用可能   [疑問点]   静的SQLではバインド変数をどう宣言すればよいですか?   [SQL*Plus]・[動的SQL]は例文がありました   ●SQL*Plusでの宣言方法    (例)     SQL> set null '<null>'     SQL> set head off     SQL> variable var_at_sqlplus number   ●動的SQLの記述方法    (例)     declare      v_sql varchar2(256);      v_id varchar2(3);     begin      v_sql = 'select id into :v_id from test';      execute immediate v_sql into v_id;     end;   ●静的SQL ・・・【 エラーになる 】     declare      variable v_id varchar2(3);     begin      select id into :v_id from test'     end; どんな事でもかまいませんので回答よろしくお願いします

  • 動的なSQLからカーソルを返す。

    下記のようなカーソルを返すパッケージがあったとします。 CREATE OR REPLACE PACKAGE TEST AS CURSOR C1 IS SELECT * FROM テーブル; TYPE TC1 IS REF CURSOR RETURN C1%ROWTYPE; PROCEDURE P_TEST(in条件 IN CHAR, CU OUT TC1); END; CREATE OR REPLACE PACKAGE BODY TEST IS PROCEDURE P_TEST(in条件 IN CHAR, CU OUT TC1) AS sqlStr VARCHAR2(1000); cur NUMBER; r NUMBER; BEGIN cur := DBMS_SQL.OPEN_CURSOR; sqlStr := 'OPEN CU FOR SELECT * FROM テーブル WHERE 条件 = ' || in条件; DBMS_SQL.PARSE(cur, sqlStr, DBMS_SQL.NATIVE); DBMS_SQL.DEFINE_COLUMN(cur, 1, CU); r := DBMS_SQL.EXECUTE(cur); DBMS_SQL.CLOSE_CURSOR(cur); END; SELECTした結果のカーソル(CU)をクライアントで取得したいのですけど 技術的に可能でしょうか? ストアドのコンパイル時に→DBMS_SQL.DEFINE_COLUMN(cur, 1, CU);が エラーとなります。 DBMS_SQL.DEFINE_COLUMNではカーソルタイプは取得できないとわっかたの ですがカーソルを取得する為のDBMS_SQL.DEFINE_COLUMNにかわる DBMS_SQL.?????はないでしょうか? いろいろ調べたのですが手に負えず。 どなたか教えてください。

  • 動的に生成したカラムを使ったFUNCTION

    レコード型の使用方法がわからないので、悪戦苦闘しております。。。 【やりたいこと】 ・あるテーブルのある項目でGROUP BYし、別の項目事に集計した結果を  カラムとして出力 クロス集計と呼ぶのでしょうか? 上記の結果表を取得出来るFUNCTIONを作成したいのです。 【サンプルデータ】 CREATE TABLE t1 ( col1 integer ,col2 integer ,val integer ); INSERT INTO t1 VALUES( 1, 1, 1, ); INSERT INTO t1 VALUES( 1, 1, 1, ); INSERT INTO t1 VALUES( 2, 1, 1, ); INSERT INTO t1 VALUES( 2, 1, 1, ); INSERT INTO t1 VALUES( 3, 2, 1, ); INSERT INTO t1 VALUES( 3, 2, 1, ); INSERT INTO t1 VALUES( 4, 2, 1, ); INSERT INTO t1 VALUES( 4, 2, 1, ); ※ここでcol1、col2ともどんなデータが入っているか、わからないとします。 なので、まずcol2をDISTINCTしたものを求めました。 SELECT DISTINCT col2 FROM t1; この結果をカーソルを使ってループし、動的にカラムを作成するSQLを 作りました。 DECLARE cu refcursor; rec record; str text := 'SELECT col1 '; str2 text := ' FROM t1 GROUP BY col1 ORDER BY col1'; BEGIN OPEN cu FOR EXECUTE SELECT DISTINCT col2 FROM t1; LOOP FETCH cu INTO rec; IF NOT FOUND THEN EXIT; END IF; str := str || ', SUM( CASE WHEN col2 = rec.col2 THEN val END ) AS col_name' || rec.col2; END LOOP; CLOSE cu; RAISE INFO 'key = %', str || str2;  動的に生成されたSQLを実行したい ------------------------------------------------------- ※ちなみに動的に生成されたSQLはこんな感じになります。 SELECT col1 ,SUM( CASE WHEN col2 = 1 THEN val END ) AS col_name1 ,SUM( CASE WHEN col2 = 2 THEN val END ) AS col_name2 FROM t1 GROUP BY col1 ORDER BY col1; ------------------------------------------------------- あとがわかりません。。動的なカラムなので、どうやって取得すれば 良いのでしょうか? レコード型を使うと上手くいくのでしょうか? 試しにFUNCTION( func1 )の戻り値をRETURNS SETOF record として 内部で rec1 record; : :  FOR rec1 IN EXECUTE str || str2 LOOP RETURN NEXT rec1; END LOOP; RETURN; SELECT * FROM func1(); とやってみたら、 ERROR: a column definition list is required for functions returning "record" となります。。。 カラムの定義が必要だと言われているんだと思いますが、カラムは 動的になっているので、どうすれば良いのでしょうか??

  • ストアドで別スキーマのテーブルを参照したい

    Oracleのストアドで以下のことを実行したいです。 1.aユーザのaテーブルにあるユーザ情報(=スキーマ名になっています)を取得 2.取得したユーザ情報(=スキーマ名)を元にスキーマ.テーブル名で  テーブルの情報を参照する 3.スキーマ.テーブル名で参照したテーブルの情報を元に  他のテーブルのデータを参照する 1については取得できたのですが、2以降を別ストアドで作成して スキーマ名を引き渡そうかと思ったのですが、実行すると 「表またはビューが存在しません」と表示されます。 実現できる方法をご教授ください。 CREATE OR REPLACE PROCEDURE del_datatbl(con_user IN VARCHAR2, del_date IN DATE) IS TYPE cur_typ IS REF CURSOR; v_inv_cursor cur_typ; -- Declare a cursor variable v_inv_query VARCHAR2(200); v_inv_num NUMBER; v_inv_cust VARCHAR2(20); v_inv_amt NUMBER; w_date DATE; BEGIN IF(del_date IS NULL) THEN w_date := ADD_MONTHS(SYSDATE,-18); ELSE w_date := del_date; END IF; v_inv_query := 'SELECT clm_mjres_MSEQ FROM ' || con_user || '.T_MNGJRES' || ' WHERE TO_CHAR(CLM_MJRES_DATE,'|| 'YYYY/MM/DD' || ') <= TO_CHAR(w_date,' || 'YYYY/MM/DD' || ')'; DBMS_OUTPUT.PUT(v_inv_query); OPEN v_inv_cursor FOR v_inv_query USING v_inv_num; LOOP FETCH v_inv_cursor INTO v_inv_num; DBMS_OUTPUT.PUT(v_inv_num); EXIT WHEN v_inv_cursor%NOTFOUND; END LOOP; CLOSE v_inv_cursor; END; . run show errors

  • VBからストアドの動的SQLを呼んで値をレコードセットで取得する方法

    お世話になります。 VBからストアドの動的SQLを呼んで、VB側で値をレコードセットで取得する方法を探しています。 ■ストアド CREATE OR REPLACE PACKAGE SAMPLE as CURSOR c2 IS select A from TBL; TYPE TANTOYOSANDATA IS REF CURSOR RETURN c2%ROWTYPE; PROCEDURE GetNUMBER(C IN NUMBER,           CU OUT TANTOYOSANDATA); end; / -- CREATE OR REPLACE PACKAGE BODY SAMPLE IS PROCEDURE GetNUMBER(C IN NUMBER,             CU OUT TANTOYOSANDATA) IS CUR INTEGER; STATUS INTEGER; ROW_PROCESSED INTEGER; A NUMBER; BEGIN --カーソルをOPENする CUR :=DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(CUR,'SELECT A FROM TBL ',DBMS_SQL.V7); DBMS_SQL.DEFINE_COLUMN(CUR,1,A); ROW_PROCESSED :=DBMS_SQL.EXECUTE(CUR); STATUS :=DBMS_SQL.FETCH_ROWS(CUR); WHILE (STATUS <> 0) LOOP DBMS_SQL.COLUMN_VALUE(CUR,1,A); STATUS :=DBMS_SQL.FETCH_ROWS(CUR); END LOOP; END; END SAMPLE; / ■VB側 Set GoORASESSION = CreateObject("OracleInProcServer.XOraSession") Set GoORADATABASE = GoORASESSION.OpenDatabase(dbname, cnuser, ORADB_DEFAULT) Set Recordset = GoORADATABASE.CreatePLSQLDynaset("Begin SAMPLE.GetTANTOINFO(1,:CU)); end;", "CU", ORADYN_DEFAULT) ' If Recordset.EOF Then Do While Not Recordset.EOF Label11.Caption = Recordset(0) Recordset.movenext  Loop 復帰値をRecordSetで受けて それをまわしながら1レコードずつ取得する方法を探しています よろしくお願いします。

  • PL/SQLでの処理について

    キーの異なる2つのトランザクションテーブルA,Bに マスタCの値を引っ張ってきて各A,B埋める処理を、テーブル名を引数にPL/SQLのプロシージャにしたいのですが、良い方法はありますか? 以下のイメージです。 <TABLE A> KEY_A C_CD C_VALUE -----+----+------- 1 3 2 3 3 1 <TABLE B> KEY_B C_CD C_VALUE -----+----+------- 1 3 2 3 3 1 <TABLE C> C_CD C_VALUE ----+-------- 1 A 2 B 3 C SQL>EXECUTE foo('A'); <TABLE A> KEY_A C_CD C_VALUE -----+----+------- 1 3 C 2 3 C 3 1 A SQL>EXECUTE foo('B'); <TABLE B> KEY_B C_CD C_VALUE -----+----+------- 1 3 C 2 3 C 3 1 A <処理イメージ> CREATE OR REPLACE PROCEDURE FOO(TNAME VARCHA2) IS c_cd NUMBER; C1 INTEGER; SQL1 VARCHAR2(2000); I INTEGER; BEGIN SQL1 := 'SELECT c_cd FROM ' || tname; C1 := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(C1, SQL1, DBMS_SQL.V7); DBMS_SQL.DEFINE_COLUMN(C1, 1, c_cd); LOOP IF DBMS_SQL.FETCH_ROWS(C1) > 0 THEN DBMS_SQL.COLUMN_VALUE(C1, 1, c_cd); UPDATE tname set value = c_cd; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ↑ここの部分をうまくかけないでしょうか? ELSE EXIT; END IF; END LOOP; end /