创建连接本地或外部过程的接口。
CREATE [ OR REPLACE ] PROCEDURE [ owner.]procedure-name ( [ parameter[, ... ] ] ) [ SQL SECURITY { INVOKER | DEFINER } ] [ RESULT ( result-column [, ... ] ) | NO RESULT SET ] [ DYNAMIC RESULT SETS integer-expression ] { EXTERNAL NAME 'native-call' | EXTERNAL NAME 'c-call' LANGUAGE { C_ESQL32 | C_ESQL64 | C_ODBC32 | C_ODBC64 } | EXTERNAL NAME 'clr-call' LANGUAGE CLR | EXTERNAL NAME 'perl-call' LANGUAGE PERL | EXTERNAL NAME 'php-call' LANGUAGE PHP | EXTERNAL NAME 'java-call' LANGUAGE JAVA }
parameter : [ parameter-mode ] parameter-name data-type [ DEFAULT expression ] | SQLCODE | SQLSTATE
parameter-mode : IN | OUT | INOUT
native-call : [ operating-system:]function-name@library
result-column : column-name data-type
c-call : [ operating-system:]function-name@library; ...
clr-call : dll-name::function-name( param-type-1[, ... ] )
perl-call : <file=perl-file> $sa_perl_return = perl-subroutine( $sa_perl_arg0[, ... ] )
php-call : <file=php-file> print php-func( $argv[1][, ... ] )
java-call : [package-name.]class-name.method-name method-signature
operating-system :
Unix
method-signature : ( [ field-descriptor, ... ] ) return-descriptor
field-descriptor 和 return-descriptor: { Z | B | S | I | J | F | D | C | V | [descriptor | Lclass-name; }
您可以创建用于调用使用各种编程语言编写的外部或本地过程的永久存储过程。可使用 PROC 作为 PROCEDURE 的同义词。
OR REPLACE 子句 指定 OR REPLACE 将创建一个新过程或替换同名的现有过程。此子句将更改过程的定义,但保留现有特权。如果尝试替换已使用的过程,则将返回错误。
参数 参数名必须符合其它数据库标识符(如列名)的规则。它们必须是有效的 SQL 数据类型。
参数可以使用关键字 IN、OUT 或 INOUT 作为前缀。如果未指定上述任何值,则缺省情况下将使用 INOUT 参数。这些关键字具有以下含义:
IN 此参数是一个为过程提供值的表达式。
OUT 此参数是一个可由过程赋值的变量。
INOUT 此参数是一个为过程提供值的变量,并且可由过程赋值。
使用 CALL 语句执行过程时,不需要指定所有参数。如果在 CREATE PROCEDURE 语句中提供了缺省值,缺少的参数会被分配缺省值。如果 CALL 语句中既未提供参数也未设置缺省值,则会给出错误。
SQLSTATE 和 SQLCODE 是特殊 OUT 参数,它们在过程结束时输出 SQLSTATE 或 SQLCODE 值。在过程调用后可立即检查 SQLSTATE 和 SQLCODE 特殊值,以测试过程的返回状态。
SQLSTATE 和 SQLCODE 特殊值会由下一个 SQL 语句修改。如果将 SQLSTATE 或 SQLCODE 作为过程参数提供,则会允许返回代码存储在变量中。
指定 OR REPLACE (CREATE OR REPLACE PROCEDURE) 将创建一个新过程或替换同名的现有过程。此子句将更改过程的定义,但保留现有特权。如果尝试替换已使用的过程,则将返回错误。
您无法创建 TEMPORARY 外部调用过程。
RESULT 子句 RESULT 子句声明结果集中的列的数量和类型。RESULT 关键字后面括在括号内的列表定义结果的列名和类型。描述 CALL 语句时,嵌入式 SQL DESCRIBE 或 ODBC SQLDescribeCol 会返回此信息。
嵌入式 SQL(LANGUAGE C_ESQL32、LANGUAGE C_ESQL64)或 ODBC(LANGUAGE C_ODBC32、LANGUAGE C_ODBC64)外部过程可返回 0 或 1 个结果集。
Perl 或 PHP(LANGUAGE PERL、LANGUAGE PHP)外部过程不能返回结果集。调用由数据库服务器装载的本地函数的过程不能返回结果集。
CLR 或 Java(LANGUAGE CLR、LANGUAGE JAVA)外部过程可返回 0、1 或更多个结果集。
视执行方式而定,某些过程可产生多个结果集,并且列数也不同。例如,以下过程在有些情况下会返回两列,而在有些情况下则会返回一列。
CREATE PROCEDURE names( IN formal char(1)) BEGIN IF formal = 'n' THEN SELECT GivenName FROM GROUPO.Employees ELSE SELECT Surname, GivenName FROM Employees END IF END; |
包含可变结果集的过程必须用不带 RESULT 子句的语句编写,或者用 Transact-SQL 编写。它们的使用受以下限制制约:
嵌入式 SQL 必须在打开用于结果集的游标之后、返回任何行之前对过程调用执行 DESCRIBE,才能获取正确形式的结果集。这需要使用 DESCRIBE 语句的 CURSOR cursor-name 子句。
ODBC、OLE DB、ADO.NET 使用这些接口的应用程序可以使用可变结果集过程。结果集的正确描述由驱动程序或提供程序完成。
Open Client 应用程序 Open Client 应用程序可以使用可变结果集过程。
如果过程仅返回一个结果集,则应使用 RESULT 子句。有了这个子句,便可防止 ODBC 和 Open Client 应用程序在游标打开后重新描述结果集。
要处理多个结果集,ODBC 必须描述当前正在执行的游标,而不是过程的已定义结果集。因此,ODBC 不会始终按过程定义的 RESULT 子句中的定义来描述列名。为避免这种问题,请在生成结果集的 SELECT 语句中使用列的别名。
DYNAMIC RESULT SETS 子句 将此子句与 LANGUAGE CLR 和 LANGUAGE JAVA 调用一起使用。DYNAMIC RESULT SETS 子句被用来指定过程将会返回的动态结果集的数量。当指定 RESULT 子句而未指定 DYNAMIC RESULT SETS 子句时,假设动态结果集的数量为 1。当 RESULT 子句和 DYNAMIC RESULT SETS 子句都未被指定时,不应产生任何结果集,如果生成结果集,则会导致错误。
C_ESQL32、C_ESQL64、C_ODBC32 和 C_ODBC64 外部环境也可以返回结果集(如 CLR 和 JAVA),但它们仅限于一个动态结果集。
调用 Perl 或 PHP(LANGUAGE PERL、LANGUAGE PHP)外部函数的过程不能返回结果集。调用由数据库服务器装载的本地函数的过程不能返回结果集。
SQL SECURITY 子句 SQL SECURITY 子句定义该过程是作为 INVOKER(调用该过程的用户)执行还是作为 DEFINER(拥有该过程的用户)执行。缺省值为 DEFINER。对于外部调用,此子句用于为外部环境中的非限定对象引用建立所有权上下文。
指定 SQL SECURITY INVOKER 后,必须对每个调用该过程的用户加以标注,因此会使用更多内存。另外,指定 SQL SECURITY INVOKER 后,也会作为调用者进行名称解析。因此,应注意用适合的所有者限定所有对象名称(表、过程等)。例如,假定 user1 创建了以下过程:
CREATE PROCEDURE user1.myProcedure() RESULT( columnA INT ) SQL SECURITY INVOKER BEGIN SELECT columnA FROM table1; END; |
如果 user2 试图运行此过程,而表 user2.table1 不 存在,则会产生表查寻错误。另外,如果 user2.table1 存 在,则使用该表而不使用预定的 user1.table1。为了防止出现这种情况,请在语句中限定表引用(user1.table1,而不只是 table1)。
EXTERNAL NAME 子句 使用不带 LANGUAGE 属性的 EXTERNAL NAME 子句的过程用于定义一个连接本地函数(使用 C 语言等编程语言编写)的接口。该本地函数由数据库服务器装载到其地址空间中。
library 名可包含文件扩展名,通常在 Windows 中为 .dll,在 Unix 中为 .so。在没有扩展名的情况下,该软件附加平台特定的缺省库文件扩展名。以下为一个正式示例。
CREATE PROCEDURE mystring( IN instr LONG VARCHAR ) EXTERNAL NAME 'mystring@mylib.dll;Unix:mystring@mylib.so'; |
下面是使用特定于平台的缺省值编写上述 EXTERNAL NAME 子句的更简单的方法:
CREATE PROCEDURE mystring( IN instr LONG VARCHAR ) EXTERNAL NAME 'mystring@mylib'; |
如果调用,则包含此函数的库将被装载到数据库服务器的地址空间中。本地函数将作为服务器的一部分执行。在这种情况下,如果此函数导致故障,则会使数据库服务器终止。因此,建议在外部环境中装载和执行使用 LANGUAGE 属性的函数。如果函数在外部环境中导致故障,数据库服务器仍可继续运行。
对于支持 operating-system 的语法,如果不指定 operating-system,则会假定该过程在所有平台上运行。如果针对其中一个调用指定了 Unix,则会假定其它调用适用于 Windows。
EXTERNAL NAME 'c-call' LANGUAGE { C_ESQL32 | C_ESQL64 | C_ODBC32 | C_ODBC64 } 子句 要在外部环境而非数据库服务器中调用编译后的本地 C 函数,存储过程或函数应使用后跟 LANGUAGE 属性的 EXTERNAL NAME 子句来定义,其中,LANGUAGE 属性指定 C_ESQL32、C_ESQL64、C_ODBC32 或 C_ODBC64。
指定 LANGUAGE 属性后,包含此函数的库将由外部进程装载,外部函数将在该外部进程中执行。在这种情况下,如果此函数导致故障,数据库服务器仍可继续运行。
以下是一个示例过程定义。
CREATE PROCEDURE ODBCinsert( IN ProductName CHAR(30), IN ProductDescription CHAR(50) ) NO RESULT SET EXTERNAL NAME 'ODBCexternalInsert@extodbc.dll' LANGUAGE C_ODBC32; |
EXTERNAL NAME clr-call LANGUAGE CLR 子句 要在外部环境中调用 .NET 函数,过程接口应使用后跟 LANGUAGE CLR 属性的 EXTERNAL NAME 子句来定义。
CLR 存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 C# 或 Visual Basic 等 .NET 语言编写,并且在数据库服务器外(即在单独的 .NET 可执行文件内)执行过程或函数。
CREATE PROCEDURE clr_interface( IN p1 INT, IN p2 UNSIGNED SMALLINT, OUT p3 LONG VARCHAR) NO RESULT SET EXTERNAL NAME 'CLRlib.dll::CLRproc.Run( int, ushort, out string )' LANGUAGE CLR; |
EXTERNAL NAME perl-call LANGUAGE PERL 子句 要在外部环境中调用 Perl 函数,过程接口应使用后跟 LANGUAGE PERL 属性的 EXTERNAL NAME 子句来定义。
Perl 存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 Perl 编写,并且在数据库服务器外(即在 Perl 可执行实例内)执行过程或函数。
以下是一个示例过程定义。
CREATE PROCEDURE PerlWriteToConsole( IN str LONG VARCHAR) NO RESULT SET EXTERNAL NAME '<file=PerlConsoleExample> WriteToServerConsole( $sa_perl_arg0 )' LANGUAGE PERL; |
EXTERNAL NAME php-call LANGUAGE PHP 子句 要在外部环境中调用 PHP 函数,过程接口应使用后跟 LANGUAGE PHP 属性的 EXTERNAL NAME 子句来定义。
PHP 存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 PHP 编写,并且在数据库服务器外(即在 PHP 可执行实例内)执行过程或函数。
以下是一个示例过程定义。
CREATE PROCEDURE PHPPopulateTable() NO RESULT SET EXTERNAL NAME '<file=ServerSidePHPExample> ServerSidePHPSub()' LANGUAGE PHP; |
EXTERNAL NAME java-call LANGUAGE JAVA 子句 要在外部环境中调用 Java 方法,过程接口应使用后跟 LANGUAGE JAVA 属性的 EXTERNAL NAME 子句来定义。
采用 Java 接口技术的存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 Java 编写,并且在数据库服务器外(即在 Java VM 内)执行过程或函数。
以下是一个示例过程定义。
CREATE PROCEDURE HelloDemo( IN name LONG VARCHAR ) NO RESULT SET EXTERNAL NAME 'Hello.main([Ljava/lang/String;)V' LANGUAGE JAVA; |
参数的描述符以及 Java 方法的返回值具有以下含义:
字段类型 | Java 数据类型 |
---|---|
B | byte |
C | char |
D | double |
F | float |
I | int |
J | long |
L class-name; | 类 class-name 的实例。类名必须是完全限定的,而且名称中的任何点都必须替换为 /。例如,java/lang/String。 |
S | short |
V | void |
Z | Boolean |
[ | 数组的每个维度都使用一个。 |
CREATE PROCEDURE 语句在数据库中创建过程。您可以通过指定所有者的方式来为其他用户创建过程。过程可用 CALL 语句进行调用。
如果存储过程返回一个结果集,则它不能同时设置输出参数或返回一个返回值。
从多个过程引用临时表时,如果该临时表定义不一致且高速缓存引用该表的语句,则会出现潜在问题。
必须具有 CREATE PROCEDURE 系统特权才能创建归您所有的外部过程。
必须具有 CREATE ANY PROCEDURE 或 CREATE ANY OBJECT 系统特权才能创建归其他人所有的外部过程。
自动提交。
SQL/2008 外部语言环境的 CREATE PROCEDURE 是 SQL/2008 标准的核心功能,尽管 SQL Anywhere 中支持的某些它的组件是可选 SQL/2008 语言功能。这些功能的子集包括:
SQL SECURITY 子句是 SQL/2008 可选语言功能 T324。
将 LONG VARCHAR、LONG NVARCHAR 或 LONG BINARY 值传递给外部过程的能力是 SQL/2008 语言功能 T041。
使用 CREATE TABLE 或 DROP TRIGGER 等语句在外部过程中创建或修改模式对象的能力是 SQL/2008 语言功能 T653。
在外部过程中使用动态 SQL 语句(包括 CONNECT、EXECUTE IMMEDIATE、PREPARE 和 DESCRIBE 等语句)的能力是 SQL/2008 语言功能 T654。
JAVA 外部过程体现 SQL/2008 语言功能 J621。
CREATE PROCEDURE 语句的几个子句是服务商扩充。其中包括:
在 LANGUAGES 子句中支持 C_ESQL32、C_ESQL64、C_ODBC32、C_ODBC64、CLR、PERL 和 PHP 是服务商扩充。SQL/2008 标准支持将 "C" 作为 environment-name 是可选语言功能 B122。
external-call 的格式是由具体实现自行定义。
RESULT 和 NO RESULT SET 子句是服务商扩充。SQL/2008 标准使用 RETURNS 子句。
特定例程参数的可选 DEFAULT 子句是服务商扩充。
可选 OR REPLACE 子句是服务商扩充。
Transact-SQL Adaptive Server Enterprise 支持外部例程的 CREATE PROCEDURE。Adaptive Server Enterprise 支持 C 语言和 Java 语言外部例程。
![]() |
使用DocCommentXchange讨论此页。
|
版权 © 2013, SAP 股份公司或其关联公司. - SAP Sybase SQL Anywhere 16.0 |