字符串连接 select 查询未给出结果 pl/sql 脚本
String concatenation select query is not giving result pl/sql script
我正在尝试动态构造查询,但在字符串连接后 select 语句未在 pl/sql 中产生任何结果。
请帮我解决这个问题
DECLARE
person_id NUMBER;
BEGIN
DECLARE
age_where VARCHAR2(100 CHAR);
TEMP_WHERE VARCHAR2(100 CHAR) := '';
add_temp_where BOOLEAN := true;
begin
age_where := q'[ and age=28]';
IF(ADD_TEMP_WHERE) THEN
TEMP_WHERE := age_where;
END IF;
SELECT id INTO person_id FROM PERSON WHERE name = 'David' || TEMP_WHERE ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('no data');
END;
DBMS_OUTPUT.PUT_LINE('result : ' || person_id);
END;
Table 个条目
ID NAME AGE ADDRESS SALARY
-----------------------------------------------
1 David 28 PURAM 30000
2 Vimal 30 MARUR 20000
输出:
anonymous block completed
no data
result :
为此你需要动态 SQL。
SQL> DECLARE
2 person_id NUMBER;
3 age_where VARCHAR2 (100 CHAR);
4 TEMP_WHERE VARCHAR2 (100 CHAR) := '';
5 add_temp_where BOOLEAN := TRUE;
6 l_str VARCHAR2 (400);
7 BEGIN
8 age_where := q'[ and age=28]';
9
10 IF (ADD_TEMP_WHERE)
11 THEN
12 TEMP_WHERE := age_where;
13 END IF;
14
15 l_str := q'[SELECT id FROM PERSON WHERE name = 'David']' || TEMP_WHERE;
16
17 EXECUTE IMMEDIATE l_str
18 INTO person_id;
19
20 DBMS_OUTPUT.PUT_LINE ('result : ' || person_id);
21 END;
22 /
result : 1
PL/SQL procedure successfully completed.
SQL>
您的 objective 是根据输入参数在查询中使用动态谓词。这是一个经常性的任务。
最重要的想法是要意识到,您应该始终使用 绑定变量 进行生产查询,即 ommit 构造,例如 WHERE name = 'David' || TEMP_WHERE
.
PL/SQL有3个选项
使用 IF - ELSE
这是最简单的选项,其中输入参数的每个组合都有一个 IF/ELSE 分支
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where int := 1;
begin
if add_temp_where = 0 then
select id into l_person_id from person where name = l_name;
else
select id into l_person_id from person where name = l_name and age = l_age;
end if;
dbms_output.put_line(l_person_id);
end;
/
这在您的情况下可以使用一个可选参数,但不能使用更多参数。对于 3 个参数,您将需要 8 个分支。
使用 OR 禁用谓词
此选项仅使用一个 static 语句并使用 OR
逻辑来禁用不需要的参数。
请注意,我使用参数 add_temp_where
和 int
0,1 以便能够在 SQL.
中使用它
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where int := 1;
begin
select id into l_person_id from person where name = l_name and (add_temp_where = 0 or age = l_age);
dbms_output.put_line(l_person_id);
end;
/
所以基本上 if add_temp_where = 0
比谓词 age = l_age
由于快捷评估而被忽略。
如果对于所有选项查询returns相似的行数(技术上使用相同的执行计划),此选项工作正常。
它 严重失败 以防一个选项返回整个 table 而其他只有一小部分(通过索引)。
在这种情况下,您需要使用动态 SQL。
动态SQL
您对 OR
使用了与上面相同的 技巧 ,因此您生成了以下 SQL 个字符串
-- for add_temp_where = 1
select id from person where name = :1 and age = :2
-- for add_temp_where = 0
select id from person where name = :1 and (0=0 or age = :2)'
请注意,这两个语句都有两个绑定变量,因此它们可以在一个 EXECUTE IMMEDIATE
中使用,如下所示:
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where BOOLEAN := true;
--
l_sql1 varchar2(1000) := 'select id from person where name = :1 and age = :2';
l_sql2 varchar2(1000) := 'select id from person where name = :1 and (0=0 or age = :2)';
begin
execute immediate l_sql1 into l_person_id using l_name, l_age;
dbms_output.put_line(l_person_id);
execute immediate l_sql2 into l_person_id using l_name, l_age;
dbms_output.put_line(l_person_id);
end;
/
两条语句是独立的,因此可以有不同的执行计划,解决了第二个选项的问题。
此选项的更多信息和学分 and here
我正在尝试动态构造查询,但在字符串连接后 select 语句未在 pl/sql 中产生任何结果。
请帮我解决这个问题
DECLARE
person_id NUMBER;
BEGIN
DECLARE
age_where VARCHAR2(100 CHAR);
TEMP_WHERE VARCHAR2(100 CHAR) := '';
add_temp_where BOOLEAN := true;
begin
age_where := q'[ and age=28]';
IF(ADD_TEMP_WHERE) THEN
TEMP_WHERE := age_where;
END IF;
SELECT id INTO person_id FROM PERSON WHERE name = 'David' || TEMP_WHERE ;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('no data');
END;
DBMS_OUTPUT.PUT_LINE('result : ' || person_id);
END;
Table 个条目
ID NAME AGE ADDRESS SALARY
-----------------------------------------------
1 David 28 PURAM 30000
2 Vimal 30 MARUR 20000
输出:
anonymous block completed
no data
result :
为此你需要动态 SQL。
SQL> DECLARE
2 person_id NUMBER;
3 age_where VARCHAR2 (100 CHAR);
4 TEMP_WHERE VARCHAR2 (100 CHAR) := '';
5 add_temp_where BOOLEAN := TRUE;
6 l_str VARCHAR2 (400);
7 BEGIN
8 age_where := q'[ and age=28]';
9
10 IF (ADD_TEMP_WHERE)
11 THEN
12 TEMP_WHERE := age_where;
13 END IF;
14
15 l_str := q'[SELECT id FROM PERSON WHERE name = 'David']' || TEMP_WHERE;
16
17 EXECUTE IMMEDIATE l_str
18 INTO person_id;
19
20 DBMS_OUTPUT.PUT_LINE ('result : ' || person_id);
21 END;
22 /
result : 1
PL/SQL procedure successfully completed.
SQL>
您的 objective 是根据输入参数在查询中使用动态谓词。这是一个经常性的任务。
最重要的想法是要意识到,您应该始终使用 绑定变量 进行生产查询,即 ommit 构造,例如 WHERE name = 'David' || TEMP_WHERE
.
PL/SQL有3个选项
使用 IF - ELSE
这是最简单的选项,其中输入参数的每个组合都有一个 IF/ELSE 分支
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where int := 1;
begin
if add_temp_where = 0 then
select id into l_person_id from person where name = l_name;
else
select id into l_person_id from person where name = l_name and age = l_age;
end if;
dbms_output.put_line(l_person_id);
end;
/
这在您的情况下可以使用一个可选参数,但不能使用更多参数。对于 3 个参数,您将需要 8 个分支。
使用 OR 禁用谓词
此选项仅使用一个 static 语句并使用 OR
逻辑来禁用不需要的参数。
请注意,我使用参数 add_temp_where
和 int
0,1 以便能够在 SQL.
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where int := 1;
begin
select id into l_person_id from person where name = l_name and (add_temp_where = 0 or age = l_age);
dbms_output.put_line(l_person_id);
end;
/
所以基本上 if add_temp_where = 0
比谓词 age = l_age
由于快捷评估而被忽略。
如果对于所有选项查询returns相似的行数(技术上使用相同的执行计划),此选项工作正常。
它 严重失败 以防一个选项返回整个 table 而其他只有一小部分(通过索引)。
在这种情况下,您需要使用动态 SQL。
动态SQL
您对 OR
使用了与上面相同的 技巧 ,因此您生成了以下 SQL 个字符串
-- for add_temp_where = 1
select id from person where name = :1 and age = :2
-- for add_temp_where = 0
select id from person where name = :1 and (0=0 or age = :2)'
请注意,这两个语句都有两个绑定变量,因此它们可以在一个 EXECUTE IMMEDIATE
中使用,如下所示:
declare
l_person_id int;
l_name varchar2(10) := 'David';
l_age int := 28;
add_temp_where BOOLEAN := true;
--
l_sql1 varchar2(1000) := 'select id from person where name = :1 and age = :2';
l_sql2 varchar2(1000) := 'select id from person where name = :1 and (0=0 or age = :2)';
begin
execute immediate l_sql1 into l_person_id using l_name, l_age;
dbms_output.put_line(l_person_id);
execute immediate l_sql2 into l_person_id using l_name, l_age;
dbms_output.put_line(l_person_id);
end;
/
两条语句是独立的,因此可以有不同的执行计划,解决了第二个选项的问题。
此选项的更多信息和学分