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

Oracle PL/SQL:在存储过程中使用IN参数重写SELECT语句,oracle,plsql,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 (g

假设我有一个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;
请注意,
gender
中的参数在这里没有任何作用。我想要的是传入变量
gender
,该变量可能等于'male'或'female',并以某种方式在SELECT语句中使用
gender
(而不是'male')。目标是将
gender
作为一个变量传入,该变量可用于返回例如
gender
定义的男性或女性的平均体重

我知道我可能可以将IF/THEN/ELSE语句与两个单独的SELECT语句一起使用,但我想知道是否有一种优雅的方法可以只使用一个SELECT语句,将上述SELECT语句中的“male”改为其他语句

请注意,这是我前面问题的重做


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

您需要将SELECT语句组合为字符串,然后在其上使用。

我必须了解如何转换示例,但我知道在SQL Server中可以执行动态SQL。还有

它会是这样的(我只是说Oracle不是我的正常语言)


动态SQL的问题是,它的性能没有那么好。虽然不是很优雅,但是如果您只有双向if,那么我会使用if块,这样代码的性能会更好。

您需要使用与您在另一个问题中建议的相同的动态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;

但是你会遇到与你之前的问题相同的普遍反对意见——数据模型存在根本性的缺陷。您最好为
男性
女性
调查结果单独设置一行,而不是为
男性
女性
结果单独设置一列。

谢谢Justin,为什么单独设置行比设置列更好?这是一条有时不适用的一般经验法则,还是说如果可以消除列,那么增加行总是更好?男性和女性的数据总是存在的。@ggkmath-基本上总是最好至少从一个正确的标准化数据模型开始。一个适当规范化的数据模型会有一个表,表中的列有
参数
、'gender
结果',而不是
参数
男性
女性
。通常,如果您发现自己需要在运行时选择不同的表或列,那么您的数据模型就没有正确地规范化。
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;