Stored procedures 是否在HANA存储过程中的当前用户架构中创建表?

Stored procedures 是否在HANA存储过程中的当前用户架构中创建表?,stored-procedures,ddl,hana,hana-sql-script,Stored Procedures,Ddl,Hana,Hana Sql Script,我有一些存储过程,它们可以创建用于验证目的的表。这些表中的大多数在下一次执行过程时被删除 我创建了这些程序,当我运行它们时,它们运行得很好,但我的问题是,现在我们希望其他人运行这些程序,但他们不能 经过一些研究,我发现问题在于存储过程正试图写入我的模式,因此,由于用户没有访问我的模式的权限,他们将得到权限不足错误 是否有任何方法可以让存储过程在调用存储过程的模式中创建表,而不是在创建存储过程的人的模式中创建表 下面是我为测试创建的一个小存储过程: CREATE OR REPLACE PROCED

我有一些存储过程,它们可以创建用于验证目的的表。这些表中的大多数在下一次执行过程时被删除

我创建了这些程序,当我运行它们时,它们运行得很好,但我的问题是,现在我们希望其他人运行这些程序,但他们不能

经过一些研究,我发现问题在于存储过程正试图写入我的模式,因此,由于用户没有访问我的模式的权限,他们将得到权限不足错误

是否有任何方法可以让存储过程在调用存储过程的模式中创建表,而不是在创建存储过程的人的模式中创建表

下面是我为测试创建的一个小存储过程:

CREATE OR REPLACE PROCEDURE XXX.SP_TMP_TEST ()
LANGUAGE SQLSCRIPT 
SQL SECURITY INVOKER  AS
BEGIN
    CALL XXX.SP_DROP_TABLE_IF_EXISTS ('TMP_TEST');
    CREATE COLUMN TABLE TMP_TEST (TEST INTEGER);
END

GRANT EXECUTE ON XXX.SP_TMP_TEST TO USER_B;
假设用户_A在模式XXX中创建了这个存储过程

现在,每当USER_A调用它时,就会在USER_A模式中创建表TMP_TEST

假设用户_B尝试运行它。他们会得到一个错误,说两个同名的表不能存在。这是因为删除表的存储过程会从用户的模式中删除表,但创建表会尝试在用户的模式中创建表

唯一可行的方法是将SQL_SECURY更改为DEFINER,但这将允许用户_B将表创建到用户_A的模式中,我希望将表创建到用户_B的模式或用户_C或D中,无论谁调用存储过程

我希望这是有道理的

提前感谢您的时间和帮助

问候,,
莱昂纳多

这种HANA SQLScript行为确实没有记录在案

文档告诉我们,如果过程未指定
默认模式
,则会话的当前模式将用于非限定对象(即命令中未提及模式名称的对象)

如果我们依赖于此(至少在HANA 2 SP 04之前),那么我们会遇到OP所描述的情况:不是会话的当前_模式,而是过程“所在”的模式用于非限定对象

我个人认为这是一个文档错误

现在如何处理需求(可从其他用户调用的单个过程)

一种方法是在这个场景中使用动态SQL

CREATE OR REPLACE PROCEDURE do_in_my_schema()

   SQL SECURITY INVOKER 

AS
BEGIN
    
    IF (obj_exists (CURRENT_USER, 'TAB_X') = 1) THEN 
        EXEC 'DROP TABLE "'|| current_user ||'"."TAB_X"';
    END IF;
     
    EXEC 'CREATE TABLE "'|| current_user ||'"."TAB_X" (USERNAME NVARCHAR(256) PRIMARY KEY)';
   
END;
OBJ_EXISTS
函数是一个自定义函数,用于检查对象是否存在(有关定义,请参阅)

主要的“技巧”是使用
CURRENT_USER
函数指定所需操作的目标模式名称。 然后在动态SQL
EXEC
命令中执行这些命令


所有这些都与定义者的安全性设置无关。而是指定安全上下文(谁拥有创建的表)而不是表所属的名称空间(架构)。

此HANA SQLScript行为确实没有记录在案

文档告诉我们,如果过程未指定
默认模式
,则会话的当前模式将用于非限定对象(即命令中未提及模式名称的对象)

如果我们依赖于此(至少在HANA 2 SP 04之前),那么我们会遇到OP所描述的情况:不是会话的当前_模式,而是过程“所在”的模式用于非限定对象

我个人认为这是一个文档错误

现在如何处理需求(可从其他用户调用的单个过程)

一种方法是在这个场景中使用动态SQL

CREATE OR REPLACE PROCEDURE do_in_my_schema()

   SQL SECURITY INVOKER 

AS
BEGIN
    
    IF (obj_exists (CURRENT_USER, 'TAB_X') = 1) THEN 
        EXEC 'DROP TABLE "'|| current_user ||'"."TAB_X"';
    END IF;
     
    EXEC 'CREATE TABLE "'|| current_user ||'"."TAB_X" (USERNAME NVARCHAR(256) PRIMARY KEY)';
   
END;
OBJ_EXISTS
函数是一个自定义函数,用于检查对象是否存在(有关定义,请参阅)

主要的“技巧”是使用
CURRENT_USER
函数指定所需操作的目标模式名称。 然后在动态SQL
EXEC
命令中执行这些命令


所有这些都与定义者的安全性设置无关。而是指定安全上下文(谁拥有创建的表),而不是表所属的命名空间(架构)。

谢谢您的回答。不幸的是,对我需要的东西使用动态SQL将不是一个选项。我们有100多个过程,每个过程都至少有5个查询需要创建表,因此更改这些表需要花费很长时间,这将使调试变得更加困难。我在其他存储过程中使用过动态sql,它工作得很好,但为此我希望有另一种解决方案。这种要求听起来很像是最好用一种语言实现的,在这种语言中,模式可以有效地与DB对象分离。对于SQL/SQLScript,情况并非如此。由于
CREATE TABLE
不考虑会话的当前模式,因此我希望实现DB对象到DB客户机代码的创建。当然,问题还在于:为什么每个用户都必须在其模式中创建表?SQLDBS的一个主要使用场景是拥有一个被许多人使用的共享DB(=一组表)。谢谢您的回答。不幸的是,对我需要的东西使用动态SQL将不是一个选项。我们有100多个过程,每个过程都至少有5个查询需要创建表,因此更改这些表需要花费很长时间,这将使调试变得更加困难。我在其他存储过程中使用过动态sql,它工作得很好,但为此我希望有另一种解决方案。这种要求听起来很像是最好用一种语言实现的,在这种语言中,模式可以有效地与DB对象分离。对于SQL/SQLScript,情况并非如此。因为
CREATE TABLE
不尊重t的当前模式