【问题标题】:Create a table in current user schema in HANA stored procedure?在HANA存储过程的当前用户模式中创建一个表?
【发布时间】:2020-11-09 19:35:17
【问题描述】:

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

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

经过一番研究,我发现问题是存储过程试图写入我的架构,所以由于用户无权访问我的架构,他们会得到权限不足的错误。

存储过程有没有办法在调用存储过程的方案中创建表,而不是创建存储过程的人的架构?

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

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;

假设 USER_A 在 Schema XXX 中创建了这个存储过程

现在每次 USER_A 调用它时,表 TMP_TEST 都会创建到 USER_A 架构中。

假设 USER_B 尝试运行它。他们会得到一个错误,说不能存在两个同名的表。这是因为删除表的存储过程将表从 USER_B 的架构中删除,但创建表尝试在 USER_A 的架构上创建表。

这样做的唯一方法是将 SQL_SECURY 更改为 DEFINER,但这会让 USER_B 在 USER_A 的架构中创建表,并且我希望将表创建到 USER_B 的架构或 USER_C 或 D 中,无论谁调用存储过程。

我希望这是有道理的。

提前感谢您的时间和帮助。

问候, 莱昂纳多

【问题讨论】:

    标签: stored-procedures ddl hana hana-sql-script


    【解决方案1】:

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

    文档告诉我们,如果一个过程没有指定DEFAULT SCHEMA,那么会话的current_schema 将用于不合格的对象(即在命令)。

    如果我们依赖这个(至少在 HANA 2 SP 04 之前),那么我们会遇到 OP 描述的情况:而不是会话的 current_schema,过程是“ in" 用于不合格的对象。

    就个人而言,我猜这是一个文档错误。

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

    一种方法是在这种情况下使用动态 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 函数是一个自定义函数,用于检查对象是否存在(有关定义,请参见 https://www.lbreddemann.org/if-exists-would-exist/)。

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

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

    【讨论】:

    • 感谢您的回答。不幸的是,我无法选择使用动态 SQL 来满足我的需要。我们有一百多个程序,每个程序至少有 5 个查询需要创建表,因此更改某个东西需要太长时间,这会使调试变得更加困难。我在其他存储过程中使用过动态 sql,效果很好,但为此我希望有另一种解决方案。
    • 这个要求听起来很像最好用一种可以有效地将模式与 DB 对象分离的语言来实现。对于 SQL/SQLScript,情况并非如此。因为CREATE TABLE 不尊重会话的当前模式,我希望将数据库对象的创建实现到数据库客户端代码。问题当然也是:为什么每个用户都必须在他们的模式中创建表? SQL DB 的一个主要使用场景是拥有一个供许多人使用的共享 DB(=一组表)。
    猜你喜欢
    • 2017-11-16
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多