2016-04-21 147 views
0

我有下面的查询给出了一个错误,因为遇到一个符号(在使用循环的行中我尝试开发一个函数,它将动态参数作为table_name,column_name,table_id用于其他表。还有执行立即在oracle中

FUNCTION get_encryp_pass(table_name IN varchar2,column_name IN varchar2,table_id IN varchar2) RETURN VARCHAR2 
    IS 
    BEGIN 
    EXECUTE IMMEDIATE 'for c1 in (select * from' || table_name ||) loop 
     EXECUTE IMMEDIATE 'update ' || table_name || ' set ' || column_name = encrypt_val(c1.column_name) || ' where ' || table_id || ' = ' || c1.table_id and column_name is not null; 
     end loop; 
    END get_encrypt_pass; 
+0

您没有足够的单引号。例如,在附加表名后,您需要再次引用引号)。 'EXECUTE IMMEDIATE'需要一个字符串。 – Nitish

+0

@Nitesh我尝试过,但仍然得到相同的错误。 Jchomel你能解释一下吗? – Andrew

+0

示例表是什么样子的,以及该表的3个输入参数中有些可能的值是什么? – ruudvan

回答

1

这应该工作:

CREATE PROCEDURE get_encryp_pass(table_name IN varchar2, 
           column_name IN varchar2, 
           table_id IN varchar2) IS 
BEGIN 
    EXECUTE IMMEDIATE 'begin for c1 in (select * from ' || table_name || 
        ') loop update ' || table_name || ' set ' || 
        column_name || ' = encrypt_val(c1.' || column_name || 
        ') where ' || table_id || ' = c1.'||table_id||' and ' || column_name || 
        ' is not null; end loop; end;' 
    ; 
END; 

但是,为什么不只需拨打update FTP_SFTP_SERVER set PASSWORD=encrypt_val(PASSWORD) where PASSWORD is not null

+0

这意味着'table_id'是*不是*您的列的名称?在这种情况下,你必须传递另一个参数'table_id_name'。 –

+0

好的,我已经调整了程序。参数'table_id'现在是主键的列名。在我的第一个版本中,它是id的值:-) –

+0

我已经纠正它:绑定变量table_id不再使用 –

1

保持护理什么是可变的,什么是一个字符串字面而且必须是单引号,因此...和字符串变量每亩加双引号:

EXECUTE IMMEDIATE 'update ' || table_name || ' set ' || column_name || ' = ''' || encrypt_val(c1.column_name) || ''' where ' || table_id || ' = ' || c1.table_id || ' and column_name is not null'; 

最佳做法是首先将varchar2变量中的语句连接起来,然后检查t他的。如果变量的内容是正确的语法和可执行的EXECUTE IMMEDIATE应该工作以及

declare 
    stmt varchar2(4000); 
begin 
    stmt := 'update ' || table_name || ' set ' || column_name || ' = ''' || encrypt_val(c1.column_name) || ''' where ' || table_id || ' = ' || c1.table_id || ' and column_name is not null'; 
    EXECUTE IMMEDIATE stmt; 
end; 
+0

FOR - Loop不是一个简单的SELECT/INSERT/UPDATE/DELETE-Statement,所以你必须将所有的代码包装在匿名块中,比如“** begin ** for .... loop do_something; end loop; **结束**“ – oratom

+0

为什么在FOR循环中更新同一行的同一列? – ruudvan

+0

我想知道y循环是必需的吗? –

0

我想我已经为你的问题一个替代方案。在这种情况下可以使用MERGE。请尝试它,我没有workpaceso力度测试它,但它应该工作让我知道,如果它有帮助。

FUNCTION get_encryp_pass(
    table_name IN VARCHAR2, 
    column_name IN VARCHAR2, 
    table_id IN VARCHAR2) 
    RETURN VARCHAR2 
IS 
BEGIN 
    EXECUTE IMMEDIATE 'MERGE INTO '||table_name||' t1 USING 
(
SELECT * FROM '||table_name|| ')t2 
ON 
(
t1.table_id = t2.table_id 
) 
WHEN MATCHED THEN 
UPDATE SET t1.'||column_name||' = encrypt_val(t2.'||column_name||')' 
||' WHERE and t1.'||column_name||' IS NOT NULL'; 
END; 
+0

所以不能有你所传递的table_name的列名为table_id –

+0

它只适用于我检查。 Y downvote plz justify –