在oracle中立即执行

在oracle中立即执行,oracle,function,for-loop,plsql,execute-immediate,Oracle,Function,For Loop,Plsql,Execute Immediate,我在下面的查询中遇到了一个错误,它给出了一个符号(在使用循环的行中)。我正在尝试开发一个函数,该函数将动态参数作为表名、列名、表id,并用于其他表 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' || t

我在下面的查询中遇到了一个错误,它给出了一个符号(在使用循环的行中)。我正在尝试开发一个函数,该函数将动态参数作为表名、列名、表id,并用于其他表

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;

注意什么是变量,什么是字符串文字,必须单引号,因此…字符串变量必须双引号:

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变量中并检查它。如果变量的内容在语法上正确且可执行,则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;

注意什么是变量,什么是字符串文字,必须单引号,因此…字符串变量必须双引号:

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变量中并检查它。如果变量的内容在语法上正确且可执行,则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;

我想我有一个选择来回答你的问题。在这种情况下可以使用合并。请尝试它。我没有工作空间,所以不要测试它,但它应该可以工作。如果有帮助,请告诉我

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;

我想我有一个选择来回答你的问题。在这种情况下可以使用合并。请尝试它。我没有工作空间,所以不要测试它,但它应该可以工作。如果有帮助,请告诉我

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;
这应该起作用:

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;
但为什么不在密码不为空的情况下调用
updateftp\u SFTP\u SERVER set PASSWORD=encrypt\u val(PASSWORD)

这应该可以:

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\u SFTP\u SERVER set PASSWORD=encrypt\u val(PASSWORD),其中PASSWORD不为null

您没有足够的单引号。例如,在添加表名之后,您需要在前面再次加引号)
executeimmediate
需要一个字符串。@Nitesh我试过了,但仍然得到相同的错误。Jchomel您能解释一下吗?示例表是什么样子的,该表的3个输入参数中可能有哪些值?但实际上您并没有将加密密码作为字符串返回,是吗?您正在函数内部执行
更新
,并修改表中的值<代码>更新无论如何都不能在SQL内部完成。假设您不是在执行更新,而是在执行选择。想想你想要返回多少行。您要查找的是1个加密密码还是整个表?如果是整个表,则需要考虑返回数组。如果只有1个密码,则需要传入
ID
的值来标识该1行并按其进行筛选。单引号不足。例如,在附加表名之后,您需要在前面再次加引号)
executeimmediate
需要一个字符串。@Nitesh我试过了,但仍然得到相同的错误。Jchomel您能解释一下吗?示例表是什么样子的,该表的3个输入参数中可能有哪些值?但实际上您并没有将加密密码作为字符串返回,是吗?您正在函数内部执行
更新
,并修改表中的值<代码>更新无论如何都不能在SQL内部完成。假设您不是在执行更新,而是在执行选择。想想你想要返回多少行。您要查找的是1个加密密码还是整个表?如果是整个表,则需要考虑返回数组。如果它只是一个密码,那么你需要为
ID
传递一个值来识别这一行并通过它进行过滤。for-Loop不是一个简单的SELECT/INSERT/UPDATE/DELETE语句,因此你必须将你的所有代码包装在一个匿名块中,比如“begin for….Loop do\ U so某物;end Loop;end”为什么要为for循环中的同一组行更新相同的1列?一个简单的动态更新语句也可以满足要求。您的代码看起来像是要将所有未加密的“column_name”转换为它们的加密等效项。如果是,则表示更新所有行!,然后删除FOR循环以及比较单个ID的where谓词。。。只需更新全部:
update tbl1 set col1=encrypt_val(col1),其中col1不为null
FOR循环不是简单的SELECT/INSERT/update/DELETE语句,因此您必须将所有代码包装在一个匿名块中,如“begin FOR….Loop do_某事;end Loop;end”为什么要为for循环中的同一组行更新相同的1列?一个简单的动态更新语句也可以满足要求。您的代码看起来像是要将所有未加密的“column_name”转换为它们的加密等效项。如果是,则表示更新所有行!,然后删除FOR循环以及比较单个ID的where谓词。。。只需全部更新:
update tbl1 set col1=encrypt_val(col1),其中col1不为null
,因此您要传递的表名不能有名为table_id的列。我刚刚检查了它。Y downvote plz justifyso对于您要传递的表名,不能有名为table_id的列。我刚刚检查过它。Y downvote plz证明这意味着
table_id
不是您列的名称吗?在这种情况下,您必须传递另一个参数
table\u id\u name
。好的,我已经调整了过程。参数
table_id
现在是主键的列名。在我的第一个版本中,它是id的值:-)我已经更正了它:绑定变量table_id不再使用,这意味着
table_id
不是列的名称吗?在这种情况下,您必须传递另一个参数
table\u id\u name
。好的,我已经调整了过程。参数
table_id
现在是主键的列名。在我的第一个版本中,它是id的值:-),我已经更正了它:绑定变量table_id不再使用