2016-04-14 49 views
1

假設我有一個表:SQL列名稱與PL/SQL變量名稱相同 - 如何在select語句中完成此操作?

create table foo (
    col_1  number; 
    col_2  number; 
); 

然後,我有以下代碼

declare 
    col_1 number; 
    col_2 number; 
begin 
    col_1 := 1; 
    select col_2 into col_2 from foo where col_1 = col_1; 
end; 

當然如預期這將無法工作。如何在不需要更改變量名稱的情況下使其工作?

+2

我認爲你不能; [文檔](http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/nameresolution.htm#LNPLS2038)說:「如果一個SQL語句引用同時屬於列和本地變量或形式參數,那麼列名優先。「 – Aleksej

+2

即使你可以規避這種情況,將變量命名爲列名也是非常糟糕的做法......你只會對自己和任何繼承此代碼的人進行維護。大多數商店通常決定使用v_作爲變量的前綴標準化。 –

+0

@KrisJohnston - 我知道這是不好的做法。我剛剛寫了一些實驗性代碼,並沒有預期使用特定的表格。我希望能夠快速修復,以確保它在重構代碼之前能夠正常工作。 –

回答

4

你可以,如果你是「而不需要改變變量名」夠你的定義的自由主義。讀神話般PL/SQL Name Resolution說:

如果一個標識符在一個名爲PL/SQL單元中聲明,你可以用單位的名稱(塊,子程序,或限定其簡單的名稱(在其聲明中的名字)包),使用此語法:

unit_name.simple_identifier_name

下面的例子將打印20如預期:

create table foo (a number, b number); 

insert into foo values(1, 10); 
insert into foo values(2, 20); 
insert into foo values(3, 30); 

begin 
    <<bar>> 
    declare 
    a number; 
    b number; 
    begin 
    a := 2; 
    select b into bar.b from foo where a = bar.a; 
    dbms_output.put_line(b); 
    end; 
end; 
/

變量名稱未更改。相反,它們嗯......更有資格:)

注意以下不起作用:

begin 
    declare 
    a number; 
    b number; 
    begin 
    a := 2; 
    select foo.b into b from foo where foo.a = a; 
    dbms_output.put_line(b); 
    end; 
end; 
/

select語句來非合格a被解釋爲是因爲precedence rules的列:

如果SQL語句引用既屬於列又屬於本地變量或形式參數的名稱,則列名優先。

-1

試試這個:

declare 
     col_1 number; 
     col_2 number; 
    begin 
     col_1 := 1; 
     select foo.col_2 into col_2 from foo where foo.col_1 = col_1; 

     dbms_output.put_line(col_2); 

    end; 
/

表名或同義詞說,它的實體鏈接表。 也可以使用過程名稱,如果您執行過程名稱。

例如,如果PROC名稱是做什麼,你可以做到以下幾點:

select foo.col_2 into DO.col_2 from foo where foo.col_1 = DO.col_1; 
+0

我可以確認這不起作用。 –

+0

我在2版本的Oracle上檢查過它。它的工作原理 –

+0

最高位不起作用。有一個過程,它的確如此, –

1

您可以使用EXECUTE IMMEDIATE DINAMIC查詢:

declare 
    col_1 number; 
    col_2 number; 
begin 
    col_1 := 2; 
    execute immediate 'select col_2 from foo where col_1 = :a' 
    into col_2 
    using col_1; 
end; 
0

以供將來參考,並攜帶一個來自@ user272735答案 - 以下也適用

create table foo (a number, b number); 

insert into foo values(1, 10); 
insert into foo values(2, 20); 
insert into foo values(3, 30); 
/

create procedure bar 
as 
    a number; 
    b number; 
begin 
    a := 2; 
    select b into bar.b from foo where a = bar.a; 
    dbms_output.put_line(b); 
end; 
/
+0

是的,它是有效的,因爲過程(如標籤爲block(參見我的示例),函數和包也是)是一個命名的PL/SQL單元。 – user272735

+0

我想我會添加它以備將來參考。你知道它是否適用於軟件包嗎?即包名而不是函數/過程名? –

+0

我從來沒有使用過它,但根據文檔,這也適用於包。 – user272735

0

爲了完整起見,有一個更多變化我還沒有看到提及:

<<mytest>> 
declare 
    dummy dual.dummy%type := '?'; 
begin 
    select count(*) into :result from dual d where d.dummy = mytest.dummy; 
end; 

這與user272735的答案相同,但沒有包裝層。

(注意不是所有的客戶端可以支持這一點,例如PL/SQL開發人員11.1支持它在測試窗口,但不是在SQL或命令窗口。)