バージョンごとのドキュメント一覧

36.5. 動的SQL #

<title>Dynamic SQL</title>

In many cases, the particular SQL statements that an application has to execute are known at the time the application is written. In some cases, however, the SQL statements are composed at run time or provided by an external source. In these cases you cannot embed the SQL statements directly into the C source code, but there is a facility that allows you to call arbitrary SQL statements that you provide in a string variable. 多くの場合、アプリケーションが実行しなければならないSQL文は、アプリケーションを作成する段階で決まります。 しかし、中には、SQL文が実行時に構成されることや外部ソースで提供されることがあります。 このような場合、SQL文を直接Cソースコードに埋め込むことはできません。 しかし、文字列変数として提供される任意のSQL文を呼び出すことができる機能が存在します。

36.5.1. 結果セットを伴わないSQL文の実行 #

<title>Executing Statements without a Result Set</title>

The simplest way to execute an arbitrary SQL statement is to use the command <command>EXECUTE IMMEDIATE</command>. For example: 任意のSQL文を実行するもっとも簡単な方法は、EXECUTE IMMEDIATE コマンドを使用することです。 例を示します:

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "CREATE TABLE test1 (...);";
EXEC SQL END DECLARE SECTION;

EXEC SQL EXECUTE IMMEDIATE :stmt;

<command>EXECUTE IMMEDIATE</command> can be used for SQL statements that do not return a result set (e.g., DDL, <command>INSERT</command>, <command>UPDATE</command>, <command>DELETE</command>). You cannot execute statements that retrieve data (e.g., <command>SELECT</command>) this way. The next section describes how to do that. EXECUTE IMMEDIATEは結果セットを返却しないSQL文(例えば、DDL、INSERTUPDATEDELETE)に使用することができます。 結果を受け取るSQL文(例えば、SELECT)をこの方法で実行することはできません。 次の節で、その実行方法を説明します。

36.5.2. 入力パラメータを伴うSQL文の実行 #

<title>Executing a Statement with Input Parameters</title>

A more powerful way to execute arbitrary SQL statements is to prepare them once and execute the prepared statement as often as you like. It is also possible to prepare a generalized version of a statement and then execute specific versions of it by substituting parameters. When preparing the statement, write question marks where you want to substitute parameters later. For example: 任意のSQL文を実行するより強力な方法は、一度プリペアをし、その後でプリペアド文を実行したいところで実行することです。 また、SQL文を汎用化した形でプリペアし、パラメータを置き換えることで特定のSQL文を実行させることも可能です。 SQL文をプリペアする時、後でパラメータとして置き換えたいところには疑問符を記述してください。 以下に例を示します。

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE mystmt FROM :stmt;
 ...
EXEC SQL EXECUTE mystmt USING 42, 'foobar';

When you don't need the prepared statement anymore, you should deallocate it: プリペアド文が必要なくなった時、割当てを解除しなければなりません。

EXEC SQL DEALLOCATE PREPARE name;

36.5.3. 結果セットを返却するSQL文の実行 #

<title>Executing a Statement with a Result Set</title>

To execute an SQL statement with a single result row, <command>EXECUTE</command> can be used. To save the result, add an <literal>INTO</literal> clause. 単一行を編訳するSQL文を実行するには、EXECUTE を使うことができます。 結果を保存するには、INTO 句を追加します。

EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "SELECT a, b, c FROM test1 WHERE a > ?";
int v1, v2;
VARCHAR v3[50];
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE mystmt FROM :stmt;
 ...
EXEC SQL EXECUTE mystmt INTO :v1, :v2, :v3 USING 37;

An <command>EXECUTE</command> command can have an <literal>INTO</literal> clause, a <literal>USING</literal> clause, both, or neither. EXECUTEコマンドはINTO句、USING句、この両方を持つことも、どちらも持たないこともできます。

If a query is expected to return more than one result row, a cursor should be used, as in the following example. (See <xref linkend="ecpg-cursors"/> for more details about the cursor.) クエリが2行以上の結果を返すことが想定される場合、以下の例のようにカーソルを使う必要があります。 (カーソルの詳細については 36.3.2 を参照してください)

EXEC SQL BEGIN DECLARE SECTION;
char dbaname[128];
char datname[128];
char *stmt = "SELECT u.usename as dbaname, d.datname "
             "  FROM pg_database d, pg_user u "
             "  WHERE d.datdba = u.usesysid";
EXEC SQL END DECLARE SECTION;

EXEC SQL CONNECT TO testdb AS con1 USER testuser;
EXEC SQL SELECT pg_catalog.set_config('search_path', '', false); EXEC SQL COMMIT;

EXEC SQL PREPARE stmt1 FROM :stmt;

EXEC SQL DECLARE cursor1 CURSOR FOR stmt1;
EXEC SQL OPEN cursor1;

EXEC SQL WHENEVER NOT FOUND DO BREAK;

while (1)
{
    EXEC SQL FETCH cursor1 INTO :dbaname,:datname;
    printf("dbaname=%s, datname=%s\n", dbaname, datname);
}

EXEC SQL CLOSE cursor1;

EXEC SQL COMMIT;
EXEC SQL DISCONNECT ALL;