任何 SQL 命令都可以在一个嵌入式 SQL 应用中被运行。下面是一些在嵌入式 SQL 应用中运行 SQL 命令的例子。
创建一个表:
EXEC SQL CREATE TABLE foo (number integer, ascii char(16)); EXEC SQL CREATE UNIQUE INDEX num1 ON foo(number); EXEC SQL COMMIT;
插入行:
EXEC SQL INSERT INTO foo (number, ascii) VALUES (9999, 'doodad'); EXEC SQL COMMIT;
删除行:
EXEC SQL DELETE FROM foo WHERE number = 9999; EXEC SQL COMMIT;
更新:
EXEC SQL UPDATE foo SET ascii = 'foobar' WHERE number = 9999; EXEC SQL COMMIT;
返回一个单一结果行的SELECT
语句也可以直接使用EXEC SQL
执行。要处理有多行的结果集,一个应用必须使用一个游标,可参考下面的Section 33.3.2(作为一种特殊情况,一个应用可以一次取出多行到一个数组主变量中,参考Section 33.4.5.3.1)。
单行选择:
EXEC SQL SELECT foo INTO :FooBar FROM table1 WHERE ascii = 'doodad';
正常连接后,使用 EXEC SQL
执行 SELECT
、INSERT
、
UPDATE
、DELETE
、游标、匿名块、动态 SQL 时都会开启事务。
如果没有其他操作,务必使用EXEC SQL COMMIT;
提交事务。如果执行的过程中,有处于idle in transaction
的事务,该事务会持有用到的表以及其他对象的锁,阻塞其他事务执行,并且增加死锁的机率。对处于idle in transaction
的事务,还执行匿名块的场景做了处理,即执行匿名块前,会提交处于idle in transaction
的事务。需要注意的是:即便匿名块
中执行报错,idle in transaction
的事务中的DML操作也不会回滚。
EXEC SQL update test_commit set a = 13; EXEC SQL EXECUTE BEGIN update_commit(17); end; END-EXEC;
LightDB Pro*C 在非自动提交模式下,执行语句前会先给服务器发送 'begin transaction',来保证非自动提交的功能。针对事务中执行的select、close 游标, 会提交执行该语句之前的所有操作,使用这个功能需要保证update、delete、insert之后执行EXEC SQL COMMIT。
还有,一个配置参数可以用SHOW
命令检索:
EXEC SQL SHOW search_path INTO :var;
:
形式的记号是主变量,即它们指向 C 程序中的变量。它们在Section 33.4中解释。
something
在执行 SQL
命令(目前特指 UPDATE
和 INSERT
语句)时,可以使用 FOR
:
来指定这个 something
SQL
语句执行的次数,
并且可以通过循环来改变 SQL
语句中 :
主变量的值。
语法如下:
something
EXEC SQL FOR :count UpdateStmt; EXEC SQL FOR :count InsertStmt;
在使用时,有以下几个注意事项:
int,numeric,short,long,long long,float,double,decimal,string,timestamp,
date,interval,bool
类型作为主变量时,仅支持声明成一维数组,超过一维,报错;
char
类型声明成一维数组的主变量时,insert,update
语句不能使用'['']'
引用到其中的元素;
varchar,bytea
类型声明作为主变量时,不能超过二维数组,超过二维数组当二维数组处理;
char
类型声明作为主变量时,可以声明成任意维数,但是在 insert,update
绑定时只能支持一维,
如下引用::var[number]
;超过一维报错。
特别注意 char
类型声明作为主变量超过三维时,下个获取的值为 (var + 1)[0]
,
与oracle是有区别的。
要检索一个保持多行的结果集,一个应用必须声明一个游标并且从该游标中取得每一行。使用一个游标的步骤如下:声明一个游标、打开它、从该游标取得一行、重复并且最终关闭它。
使用游标选择:
EXEC SQL DECLARE foo_bar CURSOR FOR SELECT number, ascii FROM foo ORDER BY ascii; EXEC SQL OPEN foo_bar; EXEC SQL FETCH foo_bar INTO :FooBar, DooDad; ... EXEC SQL CLOSE foo_bar; EXEC SQL COMMIT;
有关声明游标的更多细节,可参考DECLARE;FETCH
命令的细节则可以参考FETCH。
从数据库fetch数据到数组,如果用户没有指定fetch的条数,则会将数组的最小长度作为fetch条数, 支持char/int/short/long/long long/double/float数组类型,不支持char三维数组。
ECPG(Oracle Pro*c兼容) DECLARE
命令实际上不会导致一个语句被发送到 LightDB 后端。在OPEN
命令被执行时,游标会在后端被打开(使用后端的DECLARE
命令)。
在默认模式中,只有当EXEC SQL COMMIT
被发出时才会提交命令。嵌入式 SQL 接口也通过ecpg(Oracle Pro*c兼容)
的-t
命令行选项(见ecpg(Oracle Pro*c兼容))或者通过EXEC SQL SET AUTOCOMMIT TO ON
语句支持事务的自动提交(类似于ltsql的默认行为)。在自动提交模式中,除非位于一个显式事务块内,每一个命令都会被自动提交。这种模式可以使用EXEC SQL SET AUTOCOMMIT TO OFF
显式地关闭。
可以使用下列事务管理命令:
EXEC SQL COMMIT
提交一个进行中的事务。
EXEC SQL ROLLBACK
回滚一个进行中的事务。
EXEC SQL PREPARE TRANSACTION
transaction_id
为两阶段提交准备当前事务。
EXEC SQL COMMIT PREPARED
transaction_id
提交一个处于准备好状态的事务。
EXEC SQL ROLLBACK PREPARED
transaction_id
回滚一个处于准备好状态的事务。
EXEC SQL SET AUTOCOMMIT TO ON
启用自动提交模式。
EXEC SQL SET AUTOCOMMIT TO OFF
禁用自动提交模式。这是默认值。
当传递给 SQL 语句的值在编译时未知或者同一个语句要被使用多次时,那么预备语句就有用武之地了。
语句使用命令PREPARE
进行预备。对于还未知的值,使用占位符“?
”:
EXEC SQL PREPARE stmt1 FROM "SELECT oid, datname FROM pg_database WHERE oid = ?";
如果一个语句返回一个单一行,应用可以在PREPARE
之后调用EXECUTE
来执行该语句,同时要用一个USING
子句为占位符提供真实的值:
EXEC SQL EXECUTE stmt1 INTO :dboid, :dbname USING 1;
如果一个语句返回多行,应用可以使用一个基于该预备语句声明的游标。要绑定输入参数,该游标必须用一个USING
子句打开:
EXEC SQL PREPARE stmt1 FROM "SELECT oid,datname FROM pg_database WHERE oid > ?"; EXEC SQL DECLARE foo_bar CURSOR FOR stmt1; /* 当到达结果集末尾时,跳出 while 循环 */ EXEC SQL WHENEVER NOT FOUND DO BREAK; EXEC SQL OPEN foo_bar USING 100; ... while (1) { EXEC SQL FETCH NEXT FROM foo_bar INTO :dboid, :dbname; ... } EXEC SQL CLOSE foo_bar;
当你不再需要该预备语句时,你应该释放它:
EXEC SQL DEALLOCATE PREPARE name
;
更多有关PREPARE
的细节,可参考PREPARE。关于使用占位符和输入参数的细节,可参考Section 33.5。