Dynamic SQLでは、仮想プロシージャ内で任意のSQL コマンドを実行できます。DYNAMIC SQLは、実行前に正確なコマンド・フォームがわからない場合に便利です。
Usage
EXECUTE
IMMEDIATE <expression>
AS
<variable> <type> [, <variable> <type>]*
[
INTO
<variable>]
[USING <variable>=<expression> [, <variable>=<expression>]*]
[
UPDATE
<literal>]
Syntax
- <expression>のデータ型はSTRING または
CLOB
です。文字列の長さは、setMaxStringLength(INTEGER)
を介して設定された 文字列の長さ制限には影響されず、 利用可能な空きメモリの量にのみ影響されます; - オプションの
AS
Clauseは、実行されたSQL文字列によって返される投影シンボル名と型を定義するために使用されます。AS
Clauseのシンボルは、実行されたSQL文字列によって返されたシンボルと位置的にマッチします。変換不可能な型や、実行された SQL 文字列によって返される列の数が少なすぎる場合はエラーになります。AS
句が指定されない場合、エラーは発生しませんが、結果も返されません; - オプションの
INTO
句は、動的SQLを指定された一時テーブルに投影します。INTO
句を指定すると、動的コマンドはINSERT
とQUERY EXPRESSION
のように動作するステートメントを実行します。Dynamic SQL CommandがINTO
句で一時テーブルを作成する場合、テーブルのメタデータを定義するためにAS
句が必要です; USING
句により、動的SQL文字列に、実行時に指定された値にバインドされる変数参照を含めることができます。これにより、SQL文字列を周囲のプロシージャ変数名や入力名からある程度独立させることができます。動的コマンドUSING
句では、各変数は短い名前のみで指定されます。ただし、動的 SQL では、USING
変数をDVAR.
に完全修飾する必要があります。USING
句は、動的SQLで正規表現として使用される値のみです。USING
句を使用してテーブル名やキーワードなどを置き換えることはできません。これにより、シンボルの使用は Prepared Statement における通常のバインド式と同等になります。USING
句は、必要な文字列操作の量を減らすのに役立ちます。USING
句の値にバインドされていない SQL 文字列のUSING
シンボルを参照すると、例外が発生します;UPDATE
句は、updating model countを指定するために使用されます。許容される値は (0, 1, *) です。INTO Clauseが指定されていない場合、0がデフォルト値です。
Examples
Dynamic SQL
以下は、動的SQL文字列のCriteriaを構築する、より複雑なアプローチを示す例です。つまり、仮想プロシージャAccountAccess.GetAccounts
はインプットID
, LastName
, bday
を持ちます。ID
に値が指定されている場合、その値のみが動的 SQL 条件で使用されます。それ以外の場合、LastName
に値が指定されると、プロシージャは値が検索文字列かどうかを検出します。LastName
に加えてbday
が指定された場合、LastName
との複合条件に使用されます。
通常、複雑なCriteriaは手順へのINPUTに基づいて形成されます。この単純な例では、Criteriaはusing Clauseを参照し、SQL文字列がプロシージャの値を直接参照しないようにしています:
BEGIN
...
DECLARE
string criteria =
'Customer.Accounts.Last = DVARS.LastName'
;
DECLARE
string sql_string =
'SELECT ID, First || '
' '
' || Last AS Name, Birthdate FROM Customer.Accounts WHERE '
|| criteria;
EXECUTE
IMMEDIATE sql_string
AS
ID
integer
,
Name
string, Birthdate
date
INTO
#
temp
USING LastName=
'some name'
;
LOOP
ON
(
SELECT
ID
FROM
#
temp
)
AS
myCursor
...
END
SQL 文字列の実行により、ID
, Name
, Birthdate
のカラムを持つ#temp
テーブルが作成されます。また、LastName
に値をバインドするために、USING
句があり、これはCriteriaで参照されていることに注意してください。この後、temp TablesはDynamic SQLの値で使用できます。
Dynamic SQL with USING Clause and Dynamically Built Criteria String
BEGIN
...
DECLARE
string crit =
null
;
IF (AccountAccess.GetAccounts.ID
IS
NOT
NULL
)
crit =
'(Customer.Accounts.ID = DVARS.ID)'
;
ELSE
IF (AccountAccess.GetAccounts.LastName
IS
NOT
NULL
)
BEGIN
IF (AccountAccess.GetAccounts.LastName ==
'%'
)
ERROR
"Last name cannot be %"
;
ELSE
IF (LOCATE(
'%'
, AccountAccess.GetAccounts.LastName) < 0)
crit =
'(Customer.Accounts.Last = DVARS.LastName)'
;
ELSE
crit =
'(Customer.Accounts.Last LIKE DVARS.LastName)'
;
IF (AccountAccess.GetAccounts.bday
IS
NOT
NULL
)
crit =
'('
|| crit ||
' and (Customer.Accounts.Birthdate = DVARS.BirthDay))'
;
END
ELSE
ERROR
"ID or LastName must be specified."
;
EXECUTE
IMMEDIATE
'SELECT ID, First || '
' '
' || Last AS Name, Birthdate FROM Customer.Accounts WHERE '
|| crit
USING ID=AccountAccess.GetAccounts.ID, LastName=AccountAccess.GetAccounts.LastName, BirthDay=AccountAccess.GetAccounts.Bday;
...
END
Known Limitations and Workarounds
Dynamic SQL Commandの使用にはいくつかのLIMITがあり、このセクションではその説明と解決策を提供します。
1. Dynamic SQL Command を使用すると、Temp Tables を使用する Assignment Statement が必要になります:
BEGIN
EXECUTE
IMMEDIATE <expression>
AS
x string
INTO
#
temp
;
DECLARE
string VARIABLES.RESULT = (
SELECT
x
FROM
#
temp
);
END
2. Criteriaの一部が存在しないと、適切なCriteriaの構築が面倒になります。例えば、"Criteria "がすでにNULL
であった場合、以下の例では、"Criteria "はNULL
のままとなります。
BEGIN
...
criteria =
'('
|| criteria ||
' and (Customer.Accounts.Birthdate = DVARS.BirthDay))'
;
...
END
優先的なアプローチとして使用する前に、基準がNULL
でないことを確認することをお勧めします。これが不可能な場合は、次の例に示すようにデフォルトを指定するのが良い方法です:
BEGIN
...
criteria =
'('
|| nvl(criteria,
'(1 = 1)'
) ||
' and (Customer.Accounts.Birthdate = DVARS.BirthDay))'
;
...
END
3. into
ResultSet
動的SQLがUPDATE
, DELETE
, INSERT
コマンドで、AS
句を指定する必要がある場合(影響を受ける行数を取得する必要がある場合)、return
列の名前と型を指定する必要があります。"AS "句から生成されたDynamic SQL列は、長さ、精度などのデフォルトのプロパティを持ちます。
EXECUTE
IMMEDIATE <expression>
AS
x
integer
INTO
#
temp
;
この名前は、期待されるUPDATEコマンドシンボル "count "と一致する必要はないことに注意してください。