在oracle中立即执行
Execute Immediate in oracle
我有以下查询,遇到符号时会出错(在使用循环的行中。我正在尝试开发一个将动态参数作为 table_name、column_name 的函数table_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;
我想我有一个替代方案可以解决你的问题。在这种情况下可以使用 MERGE。请尝试一下,我没有工作区,所以请测试一下,但它应该可以工作如果有帮助,请告诉我。
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;
但为什么不直接调用 update FTP_SFTP_SERVER set PASSWORD=encrypt_val(PASSWORD) where PASSWORD is not null
呢?
我有以下查询,遇到符号时会出错(在使用循环的行中。我正在尝试开发一个将动态参数作为 table_name、column_name 的函数table_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;
我想我有一个替代方案可以解决你的问题。在这种情况下可以使用 MERGE。请尝试一下,我没有工作区,所以请测试一下,但它应该可以工作如果有帮助,请告诉我。
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;
但为什么不直接调用 update FTP_SFTP_SERVER set PASSWORD=encrypt_val(PASSWORD) where PASSWORD is not null
呢?