pl/sql(兼容Oracle PL/SQL) 是一种块结构语言。函数、过程、包、触发器或匿名块都包含一个块结构,我们称所有包含在 匿名块 中的部分为 块 结构。
定义匿名块如下:
[ DECLAREdeclarations
] BEGINstatements
[ EXCEPTIONException-handling part
] END; /
块内每个声明和语句都以分号结尾。出现在另一个块内的块必须在 END
后面加上分号,如上所示;然而,结束函数体的最终 END
也需要一个分号,其中 /
是 pl/sql 低层块结构的结束字符。
一个常见的错误是在 BEGIN
后立即写一个分号。这是不正确的,会导致语法错误。匿名块目前不支持使用 <<label>>
。
匿名块中支持将空格转成NUMERIC,在Oracle兼容模式下生效。
例如,使用匿名块输出“quantity”的值:
DECLARE quantity integer := 80; BEGIN DBMS_OUTPUT.PUT_LINE('Quantity here is '||quantity); -- Prints 80 END; /
在使用 DBMS_OUTPUT.PUT_LINE 函数之前,需要打开打印权限。
select dbms_output.serveroutput(true);
当然,此函数只能在 Oracle 兼容模式下使用。
从 LightDB 23.4 版本开始,匿名块通过在 libpq 使用时支持绑定变量。 需要注意的是,使用绑定参数时客户端需要传递参数类型。 绑定参数的数量限制为65535。
下面是通过 libpq 执行使用绑定参数的匿名块的用例:
/* * src/test/examples/lt_testlibpq.c * * * lt_testlibpq.c * this test program shows to use LIBPQ to exec dostmt with bind param * */ #include <stdio.h> #include <stdlib.h> #include "libpq-fe.h" static void exit_nicely(PGconn *conn) { PQfinish(conn); exit(1); } int main(int argc, char **argv) { const char *conninfo; PGconn *conn; PGresult *res; const char *paramValues[10]; Oid paramTypes[10]; int nFields; int i, j; if (argc > 1) conninfo = argv[1]; else conninfo = "dbname = postgres"; conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); exit_nicely(conn); } res = PQexec(conn, "create table test_dostmt(key1 int, key2 text);"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); res = PQexec(conn, "insert into test_dostmt values(1,'a');"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); paramTypes[0] = 23; paramValues[0] = "1"; printf("update test_dostmt key2 to 'test_dostmt'\n"); res = PQexecParams(conn, "begin\ begin\ update test_dostmt set key2 = 'test_dostmt' where key1 = $1 ;\ end;\ end;", 1, paramTypes, paramValues, NULL, NULL, 0); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); printf("get test_dostmt key2 \n"); res = PQexec(conn, "select key2 from test_dostmt where key1=1;"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } nFields = PQnfields(res); /* print out the instances */ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%s: %s", PQfname(res, j), PQgetvalue(res, i, j)); printf("\n"); } PQclear(res); printf("update test_dostmt key2 to 'test_dostmt_new'\n"); paramTypes[0] = 23; paramValues[0] = "1"; paramTypes[1] = 25; paramValues[1] = "test_dostmt1"; res = PQexecParams(conn, " \ declare\ id int := $1; \ val text := $2; \ begin\ begin\ val = val || '_new'; \ update test_dostmt set key2 = val where key1 = id ;\ end;\ end;", 2, paramTypes, paramValues, NULL, NULL, 0); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); printf("get test_dostmt key2 \n"); res = PQexec(conn, "select key2 from test_dostmt where key1=1;"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } nFields = PQnfields(res); /* print out the instances */ for (i = 0; i < PQntuples(res); i++) { for (j = 0; j < nFields; j++) printf("%s: %s", PQfname(res, j), PQgetvalue(res, i, j)); printf("\n"); } PQclear(res); res = PQexec(conn, "drop table test_dostmt;"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); exit_nicely(conn); } PQclear(res); PQfinish(conn); return 0; }
pl/sql(兼容Oracle PL/SQL) 编译器会忽略注释。它们的目的是帮助其他应用程序开发人员理解您的源文本。通常,您使用注释来描述每个代码段的目的和用途。您还可以通过将它们变成注释来禁用过时或未完成的代码片段。
单行注释以 --
开始,延伸到行末。这个例子有三个单行注释。
DECLARE howmany NUMBER; num_tables NUMBER; BEGIN -- Begin processing SELECT COUNT(*) INTO howmany FROM USER_OBJECTS WHERE OBJECT_TYPE = 'TABLE'; -- Check number of tables num_tables := howmany; -- Compute another value END; /
多行注释以 /*
开始,以 */
结束,可以跨多行。
BEGIN /* IF 2 + 2 = 4 THEN some_condition := TRUE; END IF; */ NULL; END; /