我尝试在表上创建IBMi DB2掩码,如下所示:
CREATE or replace MASK IESWEBSERP.MASK_PWD_WSCONTROL ON IESWEBSERP.WSCONTROL
FOR COLUMN WSVNDPWD RETURN
CASE
WHEN ( VERIFY_GROUP_FOR_USER(SESSION_USER, 'ICC', 'IICCGRP')=1)
THEN WSVNDPWD
WHEN ( SESSION_USER in ('QSQSRVR', 'QTMHHTTP', 'PROFOUNDJS', 'IESWEBSVR'))
THEN WSVNDPWD
WHEN IESWEBSERP.IES_CHECK_AUTH( WSDTALIB ) = 1
THEN WSVNDPWD
WHEN (WSVNDID = IESWEBSERP.web_login_id )
THEN WSVNDPWD
ELSE 'MASKED'
END
ENABLE ;
问题出在IESWEBSERP.IES_CHECK_AUTH用户定义函数中使用的RETURN CASE。
根据文档,我知道RETURN CASE语句不能使用非确定性函数。因此下面是这个udf的定义:
Create or REPLACE Function IESWEBSERP.IES_CHECK_AUTH(
DATA_LIBRARY CHAR(10))
returns dec(1,0)
language SQL
NO EXTERNAL ACTION
DETERMINISTIC
NOT FENCED
SECURED
BEGIN
declare q char(1) ;
declare back char(1) ;
declare @sqlStmt1 varchar(500) ;
declare @sqlStmt varchar(500) ;
declare myCursor cursor for myStatement;
declare myCursor1 cursor for myStatement1;
set q = '''';
set @sqlStmt1 = 'select count(*) from QSYS2.TABLES WHERE TABLE_SCHEMA = '
concat q concat TRIM(DATA_LIBRARY) concat q
concat ' and TABLE_NAME = ' concat q concat 'MSTCONTL' concat q;
prepare myStatement1 from @SqlStmt1;
open myCursor1;
Fetch myCursor1 into back;
close myCursor1;
IF ( back = '1' )
THEN
SET back = '0' ;
set @sqlStmt = 'select count(*) from ' concat TRIM(DATA_LIBRARY) concat '.MSTCONTL
where USRID = SESSION_USER and (USRC2 =' concat q concat 'U' concat q
concat 'or USRC2 = ' concat q concat 'P' concat q concat')';
prepare myStatement from @SqlStmt;
open myCursor;
Fetch myCursor into back;
close myCursor;
IF ( back = '1' )
THEN SET back = '1' ;
ELSE SET back = '0' ;
END IF ;
ELSE SET back = '0' ;
END IF ;
return(back );
END;
UDF所做的一切就是检查当前会话用户的用户记录的字段MSTCONTL.USRC2的值是'U'还是'P'。如果是,它将返回值'1',这将允许用户查看字段WSVNDPWD的值,而不进行任何屏蔽。
但问题是,如果将值MSTCONTL.USRC2更新为U或P以外的值,则函数仍将返回“1”(如果之前也返回了“1”)。我认为这是因为函数被定义为DETERMINISTIC。
如果我把函数设为非确定性的,创建掩码语句就会失败。所以我不知道如何处理这种情况。我想从函数中得到一个“动态”的结果。有人能告诉我如何处理这种情况吗?
1条答案
按热度按时间j91ykkif1#
SQL语句有两种确定性:通过使用上面的
deterministic
关键字,您可以使函数具有全局确定性,这意味着它期望具有相同参数的每个调用总是返回与第一次调用时相同的结果。您可以将其改为
statement deterministic
,我想这会达到您的目的。语句确定性意味着每次在该特定语句调用中使用该语句时,该调用都将返回相同的结果,但在下一次调用该语句时,它可能会发生变化。这意味着每次使用该语句时,它都会执行一次新的查找来缓存该值,并重用该值,直到该特定调用完成。确定性语句和非确定性语句之间的最大区别是,如果有人在非确定性函数中更改了this的列值,理论上它可能会在处理结果的中途更改掩码。确定性语句不允许这样做,但它允许在两次单独运行语句之间更改掩码结果。
请注意,www.example.com上的文档https://www.ibm.com/docs/en/i/7.4?topic=statements-create-mask#fntarg_1确实说明不建议在SQL掩码过程中使用语句确定性,但它没有给予原因。我怀疑这是出于性能原因,因此您必须确定可能的性能或其他影响对于您的情况是否值得。