为什么这个动态sql查询返回变量的值而不是实际值?

时间:2013-11-11 12:07:19

标签: sql oracle dynamic-sql

我有一个存储在表格中的冲突矩阵。我试图找到价值 table [course1] [course2]但是sql拒绝合作。

这完全不起作用: 说列索引无效,但不知道为什么。

CREATE OR REPLACE PROCEDURE procedure1(course1    IN  VARCHAR2,
                                       course2    IN  VARCHAR2,
                                       conflicted OUT VARCHAR2) AS
  BEGIN

    EXECUTE IMMEDIATE 'SELECT :col1 FROM conflict_matrix_male WHERE course = :col2'
    INTO conflicted
    USING course1, course2;

    dbms_output.put_line(conflicted);
  END procedure1;

所以我尝试这样做:

CREATE OR REPLACE PROCEDURE procedure1(course1 IN VARCHAR2,
                                       course2 IN VARCHAR2) AS
  conflicted1 VARCHAR2(200);
  BEGIN

    EXECUTE IMMEDIATE 'SELECT :col1 FROM conflict_matrix_male WHERE course = :col2'
    INTO conflicted1
    USING course1, course2;

    dbms_output.put_line(conflicted1);
  END procedure1;

这会编译并运行,但它返回传递给course1的任何内容,而不是该列中的值。它不会动态地将变量的内容替换为查询。

我的最后一次尝试是:

CREATE OR REPLACE PROCEDURE checkconflict(course1    IN  VARCHAR2,
                                          course2    IN  VARCHAR2,
                                          conflicted OUT VARCHAR2) AS
  query_str VARCHAR2(1000);
  BEGIN

    query_str := 'SELECT ' || course2 ||
                 ' FROM conflict_matrix_male WHERE course = ''' || course1 || ''';';

    dbms_output.put_line(query_str);

    EXECUTE IMMEDIATE query_str INTO conflicted;

    dbms_output.put_line(conflicted);

  END checkconflict;

我运行了在第一个dbms_output中打印的sql查询,它运行得很好。但程序不起作用。我认为错误很简单,但我不知道它是什么。

编辑:

存储的内容有点像邻接矩阵。列名是除第一列以外的课程名称。 第一列是命名课程。 看起来有点像这样。

     Course     CCES1234        CEEN1235       GEEN8234        Conflicts
     CCES1234       1               1             0              2
     CEEN1235       0               1             0              1
     GEEN8234       1               1             1              3

但更大。我的目标是能够取两门课程的名称并返回价值。

例如:

  • checkConflict('CCES1234', 'CEEN1235')应该返回0
  • checkConflict('Geen8234', 'CCES1234')应返回1.

3 个答案:

答案 0 :(得分:3)

在第一个示例中,您使用列名作为参数。你不能这样做。参数只能用于替换值,而不能用于替换列名或表名。

编辑:检查新的编辑,现在很清楚,course1是列NAME,而course2是列VALUE。所以你想要的,似乎就是这样:

CREATE OR REPLACE PROCEDURE procedure1 (course1 IN VARCHAR2, course2 IN VARCHAR2,             
Conflicted OUT VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE
'SELECT ' || course1 || ' FROM conflict_matrix_male WHERE course = :crs2'
USING course2
INTO Conflicted;

DBMS_OUTPUT.PUT_LINE(Conflicted);
END;

答案 1 :(得分:1)

在上一个示例中,您倒置了course2course1,所以我认为

query_str := 'select '|| COURSE2 ||' from Conflict_matrix_male where course  = ''' || Course1 || ''';';

应该是

query_str := 'select '|| COURSE1 ||' from Conflict_matrix_male where course  = ''' || Course2 || ''';';

但您也可以使用绑定,而不是列名:

execute immediate 'Select '||course1||' from conflict_matrix_male where course = :col2'  
  into conflicted using course2;

答案 2 :(得分:1)

create or replace 
procedure CHECKCONFLICT
(
    COURSE1    in varchar2,
    COURSE2    in varchar2,
    Conflicted out varchar2
) as
query1 varchar2(200);
begin
    query1:= 'select ' || COURSE2 || ' from Conflict_matrix_male where course =''' ||    Course1 || '''';
    execute immediate query1
    into conflicted;
    dbms_output.put_line(conflicted);
 end;

小心单引号和分号。 另外,为什么不使用功能呢?我总觉得它们更容易使用。

create or replace 
function  CHECKCONFLICT4
(
    COURSE1    in varchar2,
    COURSE2    in varchar2
) 
return number
is Conflicted number;
query1 varchar2(200);
begin
    query1:= 'select ' || COURSE2 || ' from Conflict_matrix_male where course =''' || Course1 || '''';
    execute immediate query1
    into conflicted;
    return conflicted;
end;