将对象和查询的引用传递给存储过程
如果调用存储过程,并将表、视图、函数或过程的标识符传递给存储过程,您可能需要:
- Allow the stored procedure to perform SQL actions on the object, even if the stored procedure uses owner’s rights.
- Allow the stored procedure to resolve the fully qualified name of the object, if the identifier is not qualified or is partially qualified.
In these cases, you can create and pass in a reference to the object (for example, the table, view, function, or procedure). A reference is a unique identifier for an object. Within the stored procedure, when you execute SQL actions on a reference to an object, the actions are performed using the active role or secondary roles of the user who created the reference. In addition, if the object identifier is not fully qualified, the name of the object is resolved by using the current database and schema when the reference was created (in other words, the database and schema of the user who created the reference).
Similarly, if you need to pass in a query to a stored procedure and use that query in the FROM clause of a SELECT statement, you can create and pass in a query reference. Within the stored procedure, the query is performed using the active role or secondary roles of the user who created the query reference. As is the case with references to objects, if the object name in the query is not fully qualified, the name of the object is resolved by using the database and schema that were in use when the query reference was created.
本主题介绍如何创建和使用引用。
背景:与向存储过程传递对象和查询有关的问题
假设某个所有者权限存储过程旨在将行插入到一个表中,该表通过输入实参指定。以下是用 Snowflake Scripting 和 JavaScript 编写的示例:
假设您需要为另外一个角色拥有的表调用此过程:
如您调用存储过程并传入表的名称,存储过程会失败,因为存储过程的所有者没有足够的权限来访问此表:
To enable the stored procedure to perform SQL actions on the table as the caller, create a reference to the table and pass in that reference, rather than the table name.
创建引用
To create the reference, call the SYSTEM$REFERENCE function. For example:
上面的示例将以下实参传递给 SYSTEM$REFERENCE 函数:
'TABLE'for the type of the object.'table_with_different_owner'for the name of the table.'SESSION'to indicate that the reference should be scoped to the session.'INSERT'as the privilege needed to perform the action on the object.
Note
If you need to create a reference to an object that you don’t plan to modify (for example, if you are passing in a table that the stored procedure will query) and you want that reference to be valid for the scope of the call (rather than for the entire session), you can use the TABLE keyword instead of calling SYSTEM$REFERENCE. For details, see 使用 TABLE 关键字创建对表、视图或查询的引用.
指定引用范围
在传递引用的调用持续时间或会话的持续时间内,引用保持有效。创建引用的上下文决定了其范围:
-
If you create and pass a reference to a stored procedure in a single statement, the reference has the same visibility as a variable declared in the outermost block of the stored procedure:
-
If you create a reference and assign the reference to a session variable, the reference is valid for the duration of the session, even if you unset the session variable:
To specify that the scope of the reference should be the duration of the session, regardless of the context in which the
reference is created, pass 'SESSION' for the third argument (session_scope) of the SYSTEM$REFERENCE function:
在引用中授予额外的权限
By default, a reference confers a subset of privileges, based on the type of the object being referenced. For example, a reference to a table confers the SELECT privilege on that table for the active role or secondary role of the user who created the reference. The default privileges depend on the object type. For the list of supported objects, privileges, and default privileges, see Supported object types and privileges for references.
To confer additional privileges, specify those privileges as additional arguments to the SYSTEM$REFERENCE function. For example, to confer the INSERT, UPDATE, and TRUNCATE privileges on a table:
请注意,不能指定 OWNERSHIP 或 ALL 作为权限。
创建引用后,对引用创建者的权限所做的更改将体现在与引用关联的权限中。例如,如果为引用创建者撤销了 INSERT 权限,该 INSERT 权限将不再与引用关联。
将对表和视图的引用与掩码策略结合使用
When you use a reference to a table or view that has a masking policy, the reference role is the invoker role (the role returned by INVOKER_ROLE), regardless of whether the reference is used in a query, stored procedure, or user-defined function.
Using a reference does not change the current role (the role returned by CURRENT_ROLE).
在存储过程中创建引用
If you are writing an owner’s rights stored procedure, do not create a reference within the body of the stored procedure.
在所有者权限存储过程中创建的引用会使用存储过程所有者的角色。引用应使用调用存储过程的用户的角色。对于所有者权限存储过程,应该由调用存储过程的用户创建引用,并将其传递给存储过程。
如果要编写调用者权限存储过程,则可以在存储过程的正文中创建引用。
使用查询引用
如果需要传入在存储过程中 SELECT 语句的 FROM 子句中使用的查询,请创建并传入查询引用。
例如,假设存储过程传入一个 SELECT 语句,该语句的目的是在另一个 SELECT 语句的 FROM 子句中使用。在下面的示例中,查询实参应该是 SELECT 语句。此示例使用 Snowflake Scripting 和 JavaScript:
存储过程会使用所有者的权限。如果存储过程所有者没有在 SELECT 语句中查询表的权限,则对存储过程的调用将失败。
若要使存储过程能够以调用者身份执行查询,请为 SELECT 语句创建查询引用,并传入该引用而非 SELECT 语句。
To create the query reference, you can call the SYSTEM$QUERY_REFERENCE function.
Note
If you need to create a query reference that is valid for the scope of the call (rather than for the entire session), you can use the TABLE keyword instead of calling SYSTEM$QUERY_REFERENCE. For details, see 使用 TABLE 关键字创建对表、视图或查询的引用.
如果调用 SYSTEM$QUERY_REFERENCE 函数,请传入:
-
'SELECT x FROM table_with_different_owner'as the query.Note that if the SELECT statement contains any single quotes or other special characters (e.g. newlines), you must escape those characters with backslashes.
-
trueto indicate that the query reference should be scoped to the session.
例如:
在存储过程中,可以添加对查询的 FROM 子句的查询引用。例如:
For details on this function, refer to SYSTEM$QUERY_REFERENCE.
For the limitations with creating and using query references, refer to 当前限制.
使用 TABLE 关键字创建对表、视图或查询的引用¶
如果您需要创建对您没有修改且存储过程应查询的表、视图或安全视图的引用,并且希望该引用对调用范围有效(而不是对整个会话有效),请使用采用以下语法的 TABLE 关键字:
TABLE 关键字为调用表或视图的 SYSTEM$REFERENCE 函数提供了更简单的语法,无需指定对象类型的实参。使用 TABLE 关键字时,引用只授予 SELECT 权限,引用的作用范围是调用(而不是会话)。
The following examples call the stored procedure my_procedure and pass in references to tables and views:
Note
您不能将 TABLE 关键字用于函数或存储过程的名称。
如果要创建对查询的引用,且该引用只需要对调用范围有效(而不是对整个会话有效),可以使用 TABLE 关键字作为调用 SYSTEM$QUERY_REFERENCE 函数的替代方法。要使用 TABLE 关键字,请使用以下语法:
例如:
请注意以下事项:
- 不得在对象名称或查询中使用绑定变量。
- The reference created by the TABLE keyword is valid for the duration of the call. You cannot specify a different scope for the reference.
- The reference has the default privileges conferred for the type of object.
当前限制
目前,引用具有以下限制:
- GET_DDL and SYSTEM$GET_TAG do not support references as input arguments.
- 您只能创建对表、视图、函数和过程的引用。
- 在包含引用的查询中,不能使用计划缓存和结果缓存。
- 对于查询引用:
- 只能为用作内联视图的 SELECT 语句创建查询引用。
- 创建查询引用时,不能指定绑定变量或会话变量。
- 在存储过程中,只能在 SELECT 语句的 FROM 子句中使用查询引用。