繁体   English   中英

基于SAP HANA中过程的SQL更新语句

[英]SQL Update Statement based on Procedure in SAP HANA

我正在创建一个更新语句,该语句根据表名称为表列生成SHA256

第一步:我创建了一个过程,该过程获取表列,将所有列连接为一列,然后将其格式化为所需的格式。

-- Procedure code : Extract table's columns list, conctenate it and format it

Create procedure SHA_PREP (in inp1 nvarchar(20))
as 
begin

SELECT concat(concat('hash_sha256(',STRING_AGG(A, ', ')),')')  AS Names
FROM (
    SELECT  concat('to_varbinary(IFNULL("',concat(COLUMN_NAME,'",''0''))')) as A
    FROM    SYS.TABLE_COLUMNS
    WHERE SCHEMA_NAME = 'SCHEMA_NAME' AND TABLE_NAME = :inp1
    AND COLUMN_NAME not in ('SHA')
    ORDER BY POSITION 
    );
end;

/* Result of this procedures : 
hash_sha256(
to_varbinary("ID"),to_varbinary(IFNULL("COL1",'0')),to_varbinary(IFNULL("COL2",'0')) )
*/

-- Update Statement needed 

UPDATE "SCHEMA_NAME"."TABLE_NAME"
SET "SHA" = CALL "SCHEMA_NAME"."SHA_PREP"('SCHEMA_NAME')
WHERE "ID" = 99 -- a random filter

我找到了适合我需要的解决方案,但也许还有其他更简单或更合适的方法:

我将更新语句添加到我的过程中,并将所有生成的查询插入到临时表列中,并使用EXECUTE IMMEDIATE对其进行了谴责

Create procedure SHA_PREP (in inp1 nvarchar(20))
as 
begin
/* ********************************************************** */
DECLARE SQL_STR VARCHAR(5000);

-- Create a temporary table to store a query in
create local temporary table #temp1 (QUERY varchar(5000));
-- Insert the desirable query into the QUERY column (Temp Table)
insert into #temp1(QUERY)
SELECT concat('UPDATE "SCHEMA_NAME"."TABLE_NAME" SET "SHA" =' ,concat(concat('hash_sha256(',STRING_AGG(A, ', ')),')'))
FROM (
    SELECT  concat('to_varbinary(IFNULL("',concat(COLUMN_NAME,'",''0''))')) as A
    FROM    SYS.TABLE_COLUMNS
    WHERE SCHEMA_NAME = 'SCHEMA_NAME' AND TABLE_NAME = :inp1
    AND COLUMN_NAME not in ('SHA')
    ORDER BY POSITION 
    );
end;
/* QUERY : UPDATE "SCHEMA_NAME"."TABLE_NAME" SET "SHA" = 
hash_sha256(to_varbinary("ID"),to_varbinary(IFNULL("COL1",'0')),to_varbinary(IFNULL("COL2",'0'))) */
SELECT QUERY into SQL_STR FROM "SCHEMA_NAME".#temp1;

--Excuting the query 
EXECUTE IMMEDIATE (:SQL_STR);

-- Dropping the temporary table 
DROP TABLE "SCHEMA_NAME".#temp1;

/* ********************************************************** */
end;

任何其他解决方案或改进都非常受欢迎,谢谢

@SonOfHarpy提供的解决方案在技术上可行,但存在几个问题,即:

  • 不必要使用临时表
  • 过于复杂的字符串分配方法
  • 使用固定系统表架构( SYS.TABLE_COLUMNS )代替PUBLIC同义词
  • 输入参数的数据类型和变量名称错误

该代码的改进版本如下所示:

create procedure SHA_PREP (in TABLE_NAME nvarchar(256))
as 
begin
declare SQL_STR nvarchar(5000);

    SELECT 
          'UPDATE "SCHEMA_NAME"."TABLE_NAME" SET "SHA"= hash_sha256(' || STRING_AGG(A, ', ') || ')'
          into SQL_STR
    FROM (
        SELECT  
            'TO_VARBINARY(IFNULL("'|| "COLUMN_NAME" ||'",''0''))' as A
        FROM TABLE_COLUMNS
        WHERE 
                "SCHEMA_NAME" = 'SCHEMA_NAME' 
           AND "TABLE_NAME" = :TABLE_NAME
           AND "COLUMN_NAME" != 'SHA'
        ORDER BY POSITION 
        );

  --  select :sql_str from dummy; -- this is for debugging output only
    EXECUTE IMMEDIATE (:SQL_STR);
end; 

通过将CONCAT函数更改为较短的|| (双管道)运算符,因为以前嵌套的函数调用现在是简单的链接串联,所以代码变得更容易阅读。

通过使用SELECT ... INTO variable ,可以避免临时表的整个废话,这又使代码更易于理解并且不易出现问题。

现在,输入参数名称可以正确反映其含义,并映射TABLE_NAMENVARCHAR(256) )的HANA词典数据类型。

该过程现在由两个命令( SELECTEXECUTE IMMEDIATE )组成,每个命令执行该过程的基本任务:

  1. 构建有效的SQL更新命令字符串。
  2. 执行SQL命令。

我删除了无用的行注释,但在代码中保留了一条调试语句作为注释,以便无需执行命令即可查看SQL字符串。 为此,显然, EXECUTE...行需要注释掉,而调试行则必须取消注释。

比解决方案的构建更令人担忧的是其目的。 看起来好像应该将SHA列用作一种速记行数据指纹。 UPDATE方法当然可以将它作为事后思考的方式来处理,但是在执行更新时保留“指纹”。

此外,它还占用了表设计的重要部分( SHA列应包含指纹),而不是表定义。

替代方法可以是GENERATED COLUMN:

create  table test (aaa int, bbb int);
alter table test add (sha varbinary (256) generated always as 
                        hash_sha256(to_varbinary(IFNULL("AAA",'0'))
                                 ,  to_varbinary(IFNULL("BBB",'0'))
                                    )
                       );

insert into test (aaa, bbb) values (12, 32);

select * from test;

/*
AAA BBB SHA                                                             
12  32  B6602F58690CA41488E97CD28153671356747C951C55541B6C8D8B8493EB7143
*/ 

这样,“生成器”方法可以用于表定义/修改时间,但是只要表中的值发生更改,HANA就会自动完成所有实际数据处理。
同样,由于指纹将始终是最新的,因此无需单独调用该过程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM