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;
/