PL / SQL:在存储过程中使用IN参数重写SELECT语句

时间:2012-03-31 21:23:13

标签: oracle plsql

假设我有一个包含下表的Oracle 11.2数据库:

TABLE: SURVEY

PARAMETER    MALE   FEMALE 
--------------------------
SAMPLE_SIZE  102       95
AVG_WEIGHT   170      120
AVG_HEIGHT   5.9      5.4

这是一个示例最小PL / SQL存储过程,它选择男性的平均权重并将其(例如170)放入变量v_stat

PROCEDURE get_stat (gender IN VARCHAR2) 
AS
    v_stat number;
BEGIN
    SELECT male INTO v_stat FROM survey WHERE parameter = 'avg_weight';
END get_stat;

请注意IN参数gender在此处不执行任何操作。我想要的是传入变量gender,它可能等于“男性”或“女性”,并且在SELECT语句中以某种方式使用gender(而不是“男性”)。目标是将gender作为可用于返回的变量传递,例如,gender定义的男性或女性的平均权重。

我知道我可以使用带有两个单独的SELECT语句的IF / THEN / ELSE语句,但我想知道是否有一种优雅的方法可以通过将上面的SELECT语句中的“male”更改为其他语句来使用一个SELECT语句?

请注意,这是我之前提出的问题

How to programmatically set table name in PL/SQL?

(正确地)批评这不是一个现实的问题。

3 个答案:

答案 0 :(得分:5)

您需要使用与其他问题中建议的相同的动态SQL方法

PROCEDURE get_stat (gender IN VARCHAR2) 
AS
    v_sql   varchar2(1000);
    v_param varchar2(100) := 'AVG_WEIGHT';
    v_stat  number;
BEGIN
    v_sql := 'SELECT ' || gender || ' FROM survey WHERE parameter = :1';
    EXECUTE IMMEDIATE v_sql
                 INTO v_stat
                USING v_param;
END get_stat;

但是你在前面的问题中提出了同样的一般性反对意见 - 数据模型存在根本缺陷。如果为MALEFEMALE调查结果设置单独的行,而不是为malefemale结果设置单独的列,则会更好。

答案 1 :(得分:1)

您需要将SELECT语句组成字符串,然后在其上使用EXECUTE IMMEDIATELY

答案 2 :(得分:1)

我必须看看如何转换您的示例,但我知道在SQL Server中您可以执行动态SQL。而且,it appears that you can do this in Oracle也是。

它会像这样(我只是examples here,因为甲骨文不是我的正常语言)

avg_weight_str := avg_weight;
stmt_str := 'SELECT :gender INTO v_stat FROM survey WHERE parameter = :avg_weight_str';
EXECUTE IMMEDIATE stmt_str;

动态SQL的问题在于它不具备高效性。虽然不优雅,但如果你只有两种方式,那么我会使用if块,这样代码可以更高效。