Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 参考 » 使用 SQL » SQL 语句 » SQL 语句 (A-D)

 

CREATE PROCEDURE 语句(外部过程)

使用此语句创建一个连接本地或外部过程的接口。要创建 SQL 过程,请参见CREATE PROCEDURE 语句

语法
CREATE [ OR REPLACE ] PROCEDURE [ owner.]procedure-name 
     ( [ parameter, ... ] )
[ RESULT ( result-column, ... ) | NO RESULT SET ]
[ DYNAMIC RESULT SETS integer-expression ]
[ SQL SECURITY { INVOKER | DEFINER } ]
EXTERNAL NAME 'external-call' [ LANGUAGE environment-name  ] 
parameter :
  [ parameter-mode ] parameter-name data-type [ DEFAULT expression ]
| SQLCODE
| SQLSTATE
parameter-mode : IN 
| OUT 
| INOUT
result-column : column-name data-type
environment-name : 
  C_ESQL32
| C_ESQL64
| C_ODBC32
| C_ODBC64
| CLR
| JAVA
| PERL
| PHP
参数
  • CREATE PROCEDURE   您可以创建用于调用使用各种编程语言编写的外部或本地过程的永久存储过程。可使用 PROC 作为 PROCEDURE 的同义词。

    参数名必须符合其它数据库标识符(如列名)的规则。它们必须是有效的 SQL 数据类型。有关有效数据类型的列表,请参见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 数据类型

    调用嵌入式 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 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 语句中使用列的别名。

    有关从过程返回结果集的详细信息,请参见从过程返回结果

  • NO RESULT SET 子句   声明此过程不返回结果集。此声明能够促进性能提高。

  • DYNAMIC RESULT SETS 子句   将此子句与 LANGUAGE CLR 和 LANGUAGE JAVA 调用一起使用。如果不提供 DYNAMIC RESULT SETS 子句,则假定此方法不返回结果集。

    请注意,调用 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 'native-call' 子句  

    EXTERNAL NAME 'native-call'
    native-call :
    [operating-system:]function-name@library; ...
    
    operating-system : Unix
    

    使用不带 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 属性的函数。如果函数在外部环境中导致故障,数据库服务器仍可继续运行。

    有关本地库调用的信息,请参见从过程调用外部库

  • EXTERNAL NAME 'c-call' LANGUAGE {C_ESQL32 | C_ESQL64 | C_ODBC32 | C_ODBC64 } 子句  

    EXTERNAL NAME 'c-call' LANGUAGE C_ESQL32
    EXTERNAL NAME 'c-call' LANGUAGE C_ESQL64
    EXTERNAL NAME 'c-call' LANGUAGE C_ODBC32
    EXTERNAL NAME 'c-call' LANGUAGE C_ODBC64
    c-call :
    [operating-system:]function-name@library; ...
    
    operating-system : Unix
    

    要在外部环境而非数据库服务器中调用编译后的本地 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;

    有关详细信息,请参见ESQL 和 ODBC 外部环境

  • EXTERNAL NAME clr-call LANGUAGE CLR 子句  

    EXTERNAL NAME 'clr-call' LANGUAGE CLR
    clr-call :
    dll-name::function-name( param-type-1, ... )
    

    要在外部环境中调用 .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;

    有关详细信息,请参见CLR 外部环境

  • EXTERNAL NAME perl-call LANGUAGE PERL 子句  

    EXTERNAL NAME 'perl-call' LANGUAGE PERL
    perl-call :
    <file=perl-file> $sa_perl_return = perl-sub( $sa_perl_arg0, ... ) 
    

    要在外部环境中调用 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;

    有关详细信息,请参见PERL 外部环境

  • EXTERNAL NAME php-call LANGUAGE PHP 子句  

    EXTERNAL NAME 'php-call' LANGUAGE PHP
    php-call :
    <file=php-file> print php-func( $argv[1], ... ) 
    

    要在外部环境中调用 PHP 函数,过程接口应使用后跟 LANGUAGE PHP 属性的 EXTERNAL NAME 子句来定义。

    PHP 存储过程或函数的行为与 SQL 存储过程或函数基本相同,只是过程或函数的代码以 PHP 编写并且在数据库服务器外(即在 PHP 可执行实例内)执行。

    以下是一个示例过程定义。

    CREATE PROCEDURE PHPPopulateTable() 
    NO RESULT SET
    EXTERNAL NAME '<file=ServerSidePHPExample> ServerSidePHPSub()'
    LANGUAGE PHP;

    有关详细信息,请参见PHP 外部环境

  • EXTERNAL NAME java-call LANGUAGE JAVA 子句  

    EXTERNAL NAME 'java-call' LANGUAGE JAVA
    java-call :
    [package-name.]class-name.method-name method-signature
    
    method-signature : 
    ( [ field-descriptor, ... ] ) return-descriptor
    
    field-descriptor and return-descriptor :
    Z 
    | B 
    | S 
    | I 
    | J 
    | F 
    | D 
    | C 
    | V 
    | [descriptor 
    | Lclass-name;
    

    要在外部环境中调用 Java 方法,过程接口应使用后跟 LANGUAGE JAVA 属性的 EXTERNAL NAME 子句来定义。

    采用 Java 接口技术的存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 Java 编写并且在数据库服务器外(即在 Java 虚拟机内)执行。

    以下是一个示例过程定义。

    CREATE PROCEDURE HelloDemo( IN name LONG VARCHAR ) 
    NO RESULT SET
    EXTERNAL NAME 'Hello.main([Ljava/lang/String;)V'
    LANGUAGE JAVA;

    有关详细信息,请参见Java 外部环境

注释

CREATE PROCEDURE 语句在数据库中创建过程。具有 DBA 权限的用户可以通过指定所有者为其他用户创建过程。过程可用 CALL 语句进行调用。

如果存储过程返回一个结果集,则它不能同时设置输出参数或返回一个返回值。

从多个过程引用临时表时,如果该临时表定义不一致且高速缓存引用该表的语句,则会出现潜在问题。请参见在过程中引用临时表

权限

除非创建临时过程,否则必须具有 RESOURCE 权限。

引用外部过程或者为其他用户创建过程必须有 DBA 权限。

副作用

自动提交。

另请参见
标准和兼容性
  • SQL/2003   持久存储模块特性。Java 结果集的语法扩展如可选的 J621 特性中所指定。