Во многих случаях конкретные операторы SQL, которые должны выполняться приложением, известны на этапе его написания. Однако в некоторых ситуациях операторы SQL формируются во время выполнения или поступают из внешнего источника. В этих случаях вы не можете внедрить операторы SQL непосредственно в исходный код на языке C, но существует механизм, позволяющий вызывать произвольные операторы SQL, заданные в строковой переменной.
Самый простой способ выполнить произвольный оператор SQL — использовать команду EXECUTE IMMEDIATE. Например:
EXEC SQL BEGIN DECLARE SECTION; const char *stmt = "CREATE TABLE test1 (...);"; EXEC SQL END DECLARE SECTION; EXEC SQL EXECUTE IMMEDIATE :stmt;
EXECUTE IMMEDIATE может применяться для операторов SQL
, которые не возвращают набор результатов (например,
DDL, INSERT, UPDATE,
DELETE). Вы не можете выполнять операторы,
которые извлекают данные (например, SELECT) таким способом. В следующем разделе описывается, как это сделать.
Более эффективный способ выполнения произвольных операторов 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';
Когда подготовленный оператор больше не нужен, его следует удалить из памяти:
EXEC SQL DEALLOCATE PREPARE имя;
Для выполнения SQL-оператора, возвращающего одну строку результата,
EXECUTE может быть использован. Для сохранения результата добавьте
предложение предложение INTO clause.
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;
Оператор EXECUTE команда EXEC SQL может иметь предложение
предложение INTO предложение, USING предложение, оба или ни одного из них.
Если ожидается, что запрос вернет более одной строки результата, следует использовать курсор, как в следующем примере. (См. Раздел 4.3.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;
оператор 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;
оператор DISCONNECT ALL;