35.5. ÐинамиÑеÑкий SQL
Ðо Ð¼Ð½Ð¾Ð³Ð¸Ñ ÑлÑÑаÑÑ ÐºÐ¾Ð½ÐºÑеÑнÑе SQL-опеÑаÑоÑÑ, коÑоÑÑе должно вÑполнÑÑÑ Ð¿Ñиложение, извеÑÑÐ½Ñ Ð² Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð½Ð°Ð¿Ð¸ÑÐ°Ð½Ð¸Ñ Ð¿ÑиложениÑ. РнекоÑоÑÑÑ ÑлÑÑаÑÑ , однако, SQL-опеÑаÑоÑÑ ÑоÑмиÑÑÑÑÑÑ Ð²Ð¾ вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ поÑÑÑпаÑÑ Ð¸Ð· внеÑнего иÑÑоÑника. Ð ÑÑÐ¸Ñ ÑлÑÑаÑÑ SQL-опеÑаÑоÑÑ Ð½ÐµÐ»ÑÐ·Ñ Ð²Ð½ÐµÐ´ÑиÑÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно в иÑÑ Ð¾Ð´Ð½Ñй код C, но еÑÑÑ ÑÑедÑÑво, позволÑÑÑее вÑзÑваÑÑ Ð¿ÑоизволÑнÑе SQL-опеÑаÑоÑÑ, пеÑедаваемÑе в ÑÑÑоковой пеÑеменной.
35.5.1. ÐÑполнение опеÑаÑоÑов без набоÑа ÑезÑлÑÑаÑов
СамÑй пÑоÑÑой ÑпоÑоб вÑполниÑÑ Ð¿ÑоизволÑнÑй 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) Ñаким обÑазом нелÑзÑ. Ðак вÑполнÑÑÑ Ñакие опеÑаÑоÑÑ, ÑаÑÑказÑваеÑÑÑ Ð² ÑледÑÑÑем Ñазделе.
35.5.2. ÐÑполнение опеÑаÑоÑа Ñ Ð²Ñ Ð¾Ð´Ð½Ñми паÑамеÑÑами
Ðолее ÑÑÑекÑивно вÑполнÑÑÑ Ð¿ÑоизволÑнÑй 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 имÑ;35.5.3. ÐÑполнение опеÑаÑоÑа Ñ Ð½Ð°Ð±Ð¾Ñом ÑезÑлÑÑаÑов
ÐÐ»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ 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;
Ðоманда EXECUTE Ð¼Ð¾Ð¶ÐµÑ ÑодеÑжаÑÑ Ð¿Ñедложение INTO и/или пÑедложение USING, либо не ÑодеÑжаÑÑ Ð½Ð¸ Ñого, ни дÑÑгого.
ÐÑли ожидаеÑÑÑ, ÑÑо запÑÐ¾Ñ Ð²ÐµÑнÑÑ Ð±Ð¾Ð»ÐµÐµ одной ÑÑÑоки ÑезÑлÑÑаÑа, ÑледÑÐµÑ Ð¿ÑименÑÑÑ ÐºÑÑÑоÑ, как показано в ÑледÑÑÑем пÑимеÑе. (ÐодÑобно кÑÑÑоÑÑ Ð¾Ð¿Ð¸ÑÑваÑÑÑÑ Ð² ÐодÑазделе 35.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;