2016-04-21 125 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 –