CFProcparamを使用してOracleに配列またはリスト
-
30-09-2019 - |
質問
ストアドプロシージャを介してテーブルに挿入したい値のリストがあります。配列をOracleに渡して配列をループすると考えましたが、配列をOracleに渡す方法がわかりません。リストを渡しますが、PL/SQLを使用してリストを使用して配列に変える方法がわかりません(PL/SQLはかなり新しいです)。私はこれに間違った方法で近づいていますか?
Oracle 9iおよびCF8を使用します。
編集
おそらく私はこれについて間違った方法で考えていますか?ここでは新しいことをしていないと確信しています...私はリストを連想配列に変換し、オラクルがリストでうまく機能しないように見えるので、配列をループしました。
製品を追加してから、管理チームのレコードを追加しようとしています。
- 製品テーブル
ProductName = 'foo' productdescription = 'bar' ... ...
-managementTeamテーブルには、ドロップダウンから選択されたユーザーの製品のIDとIDがあります。
ユーザーIDは、「1,3,6,20」などのリストを介して渡されます
管理チームテーブルにレコードを追加するにはどうすればよいですか?
これが私がコードワイズである場所です
理論的には、inserts.addproductにリスト「1,2,3,4」を渡します。
inserts.addproductはtools.listtoarrayを呼び出して配列を返します。
inserts.addproductテストとして *デリムを含むリストを再作成します。
パッケージツールを作成または交換します
TYPE array_type is TABLE OF VARCHAR2(225) INDEX BY BINARY_INTEGER;
FUNCTION listToArray(in_list IN VARCHAR,
in_delim IN VARCHAR2 DEFAULT ',')
RETURN array_type;
END tools;
CREATE OR REPLACE PACKAGE BODY tools
AS
FUNCTION listToArray(in_list IN VARCHAR,
in_delim IN VARCHAR2 DEFAULT ',')
RETURN array_type
IS
l_token_count BINARY_INTEGER := 0;
-- l_token_tbl type_array;
i pls_integer;
l_start_pos INTEGER := 1;
l_end_pos INTEGER :=1;
p_parsed_table array_type;
BEGIN -- original work by John Spencer
WHILE l_end_pos <> 0 LOOP
l_end_pos := instr(in_list,in_delim,l_start_pos);
IF l_end_pos <> 0 THEN
l_token_count := l_token_count + 1;
p_parsed_table(l_token_count ) :=
substr(in_list,l_start_pos,l_end_pos - l_start_pos);
l_start_pos := l_end_pos + 1;
END IF;
END LOOP;
IF l_token_count = 0 THEN /* We haven't parsed anything so */
l_token_count := 1;
p_parsed_table(l_token_count) := in_list;
ELSE /* We need to get the last token */
l_token_count := l_token_count + 1;
p_parsed_table(l_token_count) := substr(in_list,l_start_pos);
END If;
RETURN p_parsed_table;
END listToArray; -- Procedure
END tools;
CREATE OR REPLACE PACKAGE inserts AS
TYPE array_type is TABLE OF VARCHAR2(225) INDEX BY BINARY_INTEGER;
PROCEDURE addProduct (inList IN VARCHAR2,
outList OUT VARCHAR2
);
END inserts;
CREATE OR REPLACE PACKAGE BODY inserts
AS
PROCEDURE addProduct (inList IN VARCHAR2,
outList OUT VARCHAR2
)
IS
i NUMBER;
localArray array_type := tools.listToArray(inList);
BEGIN
outList := '';
FOR i IN localArray.first .. localArray.last LOOP
outList := outList || '*' ||localArray(i); -- return a string just to test this mess
END LOOP;
END addProduct;
END inserts;
現在、localArray array_type:= tools.listtoArray(inlist)でエラー「pls-00382:式は間違ったタイプです」を取得しています。
最終作業コード(どうもありがとう!)
-SQLタイプコレクションを作成します
CREATE OR REPLACE TYPE array_type is TABLE OF VARCHAR2(225);
/
CREATE OR REPLACE PACKAGE tools AS
FUNCTION listToArray(in_list IN VARCHAR,
in_delim IN VARCHAR2 DEFAULT ',')
RETURN array_type;
END tools;
/
CREATE OR REPLACE PACKAGE BODY tools
AS
FUNCTION listToArray(in_list IN VARCHAR,
in_delim IN VARCHAR2 DEFAULT ',')
RETURN array_type
IS
l_token_count BINARY_INTEGER := 0;
i pls_integer;
l_start_pos INTEGER := 1;
l_end_pos INTEGER :=1;
p_parsed_table array_type := array_type();
BEGIN
WHILE l_end_pos <> 0 LOOP
l_end_pos := instr(in_list,in_delim,l_start_pos);
IF l_end_pos <> 0 THEN
p_parsed_table.extend(1);
l_token_count := l_token_count + 1;
p_parsed_table(l_token_count ) :=
substr(in_list,l_start_pos,l_end_pos - l_start_pos);
l_start_pos := l_end_pos + 1;
END IF;
END LOOP;
p_parsed_table.extend(1);
IF l_token_count = 0 THEN /* We haven't parsed anything so */
l_token_count := 1;
p_parsed_table(l_token_count) := in_list;
ELSE /* We need to get the last token */
l_token_count := l_token_count + 1;
p_parsed_table(l_token_count) := substr(in_list,l_start_pos);
END If;
RETURN p_parsed_table;
END listToArray; -- Procedure
END tools;
/
CREATE OR REPLACE PACKAGE inserts AS
PROCEDURE addProduct (inList IN VARCHAR2,
outList OUT VARCHAR2
);
END inserts;
/
CREATE OR REPLACE PACKAGE BODY inserts
AS
PROCEDURE addProduct (inList IN VARCHAR2,
outList OUT VARCHAR2
)
IS
i NUMBER;
mylist VARCHAR(100);
localArray array_type := array_type();
BEGIN
localArray := tools.listToArray(inList);
mylist := '';
FOR i IN localArray.first .. localArray.last LOOP
mylist := mylist || localArray(i) || '*';
END LOOP;
aList := mylist;
END addProduct;
END inserts;
/
解決
PL/SQLは、Oracle 8.0以降アレイをサポートしています。彼らは以前はPL/SQLテーブルと呼ばれていたので、すべての人から混乱していたので、今ではコレクションと呼ばれています。 詳細をご覧ください。
問題は、それらがユーザー定義型(IEオブジェクト)として実装されることです。の私の読書 ColdFusionドキュメント それを示唆しています cfprocparam
「プリミティブ」データ型(数、varchar2など)のみをサポートします。したがって、UDTはサポートされていません。
これが何を意味するのかわかりません:
私はリストを渡しますが、PL/SQLを使用してリストを使用して配列に変える方法がわかりません
あなたが一連のコンマ分離値を渡したいという意味なら....
"Fox in socks, Mr Knox, Sam-I-Am, The Lorax"
それから私はあなたのために回避策を持っています。 Oracleは、組み込みのトークン剤を提供しません。しかし、ずっと前に、ジョン・スペンサーはOTNフォーラムでOracle 9iで機能するハンドロールソリューションを発表しました。 ここで見つけてください。
編集
しかし...オラクルは私を嫌っています
絶望するな。 OTNフォーラムは、ジョンがそれを投稿してから数回アップグレードされており、フォーマットは途中でコードを破損したようです。使用するために使用しなかったいくつかのコンピレーションエラーがありました。
新しい機能を含むジョンのコードを書き直しました。主な違いは、ネストされたテーブルがPL/SQLタイプではなくSQLタイプとして宣言されることです。
create or replace type tok_tbl as table of varchar2(225)
/
create or replace package parser is
function my_parse(
p_str_to_search in varchar2
, p_delimiter in varchar2 default ',')
return tok_tbl;
procedure my_parse(
p_str_to_search in varchar2
, p_delimiter in varchar2 default ','
, p_parsed_table out tok_tbl);
end parser;
/
ご覧のとおり、機能は手順の単なるラッパーです。
create or replace package body parser is
procedure my_parse ( p_str_to_search in varchar2
, p_delimiter in varchar2 default ','
, p_parsed_table out tok_tbl)
is
l_token_count binary_integer := 0;
l_token_tbl tok_tbl := tok_tbl();
i pls_integer;
l_start_pos integer := 1;
l_end_pos integer :=1;
begin
while l_end_pos != 0
loop
l_end_pos := instr(p_str_to_search,p_delimiter,l_start_pos);
if l_end_pos != 0 then
l_token_count := l_token_count + 1;
l_token_tbl.extend();
l_token_tbl(l_token_count ) :=
substr(p_str_to_search,l_start_pos,l_end_pos - l_start_pos);
l_start_pos := l_end_pos + 1;
end if;
end loop;
l_token_tbl.extend();
if l_token_count = 0 then /* we haven't parsed anything so */
l_token_count := 1;
l_token_tbl(l_token_count) := p_str_to_search;
else /* we need to get the last token */
l_token_count := l_token_count + 1;
l_token_tbl(l_token_count) := substr(p_str_to_search,l_start_pos);
end if;
p_parsed_table := l_token_tbl;
end my_parse;
function my_parse ( p_str_to_search in varchar2
, p_delimiter in varchar2 default ',')
return tok_tbl
is
rv tok_tbl;
begin
my_parse(p_str_to_search, p_delimiter, rv);
return rv;
end my_parse;
end parser;
/
SQLでタイプを宣言する美徳は、次のような句で使用できることです。
SQL> insert into t23
2 select trim(column_value)
3 from table(parser.my_parse('Fox in socks, Mr Knox, Sam-I-Am, The Lorax'))
4 /
4 rows created.
SQL> select * from t23
2 /
TXT
------------------------------------------------------------------------------
Fox in socks
Mr Knox
Sam-I-Am
The Lorax
SQL>