Oracle 11 PL SQL使用Execute Immediate将值赋给变量

M_6*_*_66 0 oracle plsql

我是PL SQL的新手并且还在学习,但我需要解决一个问题而且我不太了解PL SQL来快速解决我的问题.

我引用了两个表:用户和属性.我有一个带3个参数的过程:attrib_id,uid, attrib_value.

我首先使用attrib_id查询属性表以返回属性名称并将其分配给变量.我的代码到目前为止.

接下来,我想在另一个select语句中使用从前一个select语句创建的变量来查询users表,并返回与该变量所代表的属性关联的当前值.

码:

PROCEDURE value_update_proc_z(attrib_id INTEGER, uid IN VARCHAR2, attrib_value IN VARCHAR2)

IS
    v_old_attrib_name attributes.attribute_name%TYPE;
    v_oldattrib_value varchar2(100);
    v_mymsg varchar2(2000);

BEGIN
    EXECUTE IMMEDIATE 'SELECT attrib_name FROM attributes WHERE indx = ''' || attrib_id || '''' INTO v_old_attrib_name;

    EXECUTE IMMEDIATE 'SELECT' || v_old_attrib_name || 'FROM USERS WHERE USERID = ''' || uid || '''' INTO v_oldattrib_value;

    v_mymsg := v_old_attrib_name || ' ' || v_oldattrib_value;

END value_update_proc_z;
Run Code Online (Sandbox Code Playgroud)

第一个查询应该根据传递给过程的数字从属性表中返回一个值.例如,如果attrib_id = 1,则查询将返回first_name,如果attrib_id = 2,则返回last_name,如果attrib_id = 3,则返回电子邮件.返回的值将分配给变量v_old_attrib_name.

在我的select语句中使用变量v_old_attrib_name,我希望第二个查询将返回一个值,例如; last_name将返回williams,否则电子邮件将返回bob@somewhere.com.此查询的结果将分配给变量v_oldattrib_value.

目前,第一个Execute Immediate工作,当我显示消息时,我可以看到该变量的值,但是当我添加第二个Execute Immediate时,我收到一条消息,说明操作无法完成.这不是系统生成的错误,而是由前一位开发人员设置的消息.

我愿意接受改进建议.

谢谢!

APC*_*APC 5

动态SQL很难,因为它将编译错误转变为运行时错误.令人惊讶的是,使用动态SQL在这里发布的问题是一个简单的拼写错误,如果该语句是作为静态SQL编写的话很容易发现.这似乎就是这种情况.

这里的标准建议是首先以静态形式编写SQL,因此您知道代码可以正常工作.然后将其转换为模板SQL以进行动态执行,注意空格,名称等.您的第二个语句是在连接v_old_attrib_name变量的任一侧模板SQL中缺少空格 .

此外,如果静态SQL有效,请不要使用动态SQL.例如,你的第一个陈述可以 - 而且应该是 - 静态的.

PROCEDURE value_update_proc_z(
    attrib_id INTEGER, 
    uid IN VARCHAR2, 
    attrib_value IN VARCHAR2)

IS
    v_old_attrib_name attributes.attribute_name%TYPE;
    v_oldattrib_value varchar2(100);
    v_mymsg varchar2(2000);

BEGIN
    SELECT attrib_name 
    INTO v_old_attrib_name
    FROM attributes 
    WHERE indx = attrib_id  ;

    EXECUTE IMMEDIATE 
        'SELECT ' || v_old_attrib_name || ' FROM USERS WHERE USERID = :1' 
        INTO v_oldattrib_value
        using uid;

    v_mymsg := v_old_attrib_name || ' ' || v_oldattrib_value;

   dbms_output.put_line(v_mymsg);

END value_update_proc_z;
Run Code Online (Sandbox Code Playgroud)

刚在你的问题中注意到这一行.

"这不是系统生成的错误,而是由前一位开发人员设置的消息."

天哪但看起来这个以前的开发者是坏代码王子.他们不仅通过可怕的EAV实施来愚弄你,而且他们也在抑制错误信息.诸如操作之类的通用消息无法完成对任何人都不利,尤其是对我们而言.您需要知道实际的PL/SQL错误消息,以便了解程序失败的原因,这是解决问题的关键.

现在,设计良好的系统将具有某种形式的日志记录,用于显示和/或存储真正的SQLERRM.您似乎并没有在设计良好的系统上工作,但是您是否有任何错误记录?