Oracle SQL替换变量,替换范围
Oracle SQL substitution variable, the scope of substitution
我一直在思考我实际上可以将什么以及多少放入替代变量中。我们可以只用它来替换单个 'entity' 而不是一串命令吗?我发现如果我想替换一块实际的 SQL,它不起作用(在 SqlDeveloper 中)。
我想知道如何解决这个问题...
/*------test--------------*/
CREATE TABLE Test_Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(1,'LN_1','FN_1');
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(2,'LN_2','FN_2');
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(3,'LN_21','FN_2');
commit;
--------------sub-table, worked!---
set define #;
define first_name_input = 'FN_2';
define last_name_input = 'LN_2';
define tbl_Test_Persons = 'Test_Persons';
define temp_tbl_Test_Persons_FN = 'Test_Persons_FN';
with
#temp_tbl_Test_Persons_FN as
(
select * from #tbl_Test_Persons tp
where tp.FIRSTNAME = '#first_name_input'
)
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input';
set define off;
--------------sub-table, replace the entire with clause, does NOT work - 'Invalid value for DEFINE command.'!---
set define #;
define first_name_input = 'FN_2';
define last_name_input = 'LN_2';
define tbl_Test_Persons = 'Test_Persons';
define temp_tbl_Test_Persons_FN = 'Test_Persons_FN2';
define with_clause = '
with
#temp_tbl_Test_Persons_FN as
(
select * from #tbl_Test_Persons tp
where tp.FIRSTNAME = ''#first_name_input''
)
';
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input';
set define off;
From the documentation(对于 SQL*Plus 但也适用于 SQL 开发人员):
If the value of a defined variable extends over multiple lines (using the SQL*Plus command continuation character), SQL*Plus replaces each continuation character and carriage return with a space.
SQL 开发人员的行为 略有 不同,并将继续字符留在字符串中,这没有帮助。但是它也留下了换行符,所以你可以将连续字符从 -
加倍到 --
以阻止它引起问题,因为它随后被视为注释;所以你可以这样做:
define with_clause = '--
with--
#temp_tbl_Test_Persons_FN as--
(--
select * from #tbl_Test_Persons tp--
where tp.FIRSTNAME = ''#first_name_input''--
)--
';
但还有一个更复杂的问题,因为 #with_clause
未被识别为命令 - 因为您尚未进入命令替换不会发生。您可以使用子查询来解决这个问题:
select * from (
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input'
);
这并不理想。但是,如果您这样做,脚本输出 window 会显示正在发生的替换,并且您会返回一行:
old:select * from (
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input'
)
new:select * from (
--
with--
Test_Persons_FN2 as--
(--
select * from Test_Persons tp--
where tp.FIRSTNAME = 'FN_2'--
)--
select * from Test_Persons_FN2 tp
where tp.LASTNAME = 'LN_2'
)
PERSONID LASTNAME FIRSTNAME
---------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 LN_2 FN_2
(此外,有趣的是,这在 SQL 中仍然不起作用*另外,如果您使用 #
作为替换字符 - 您会得到 "ORA-24333: zero iteration count"。它不会得到&
的那个错误;我还没有尝试过任何其他的。你必须回到单个连接字符。但即使进行了这些更改,它仍然不能正确地替换 with
子句。还不确定为什么。)
我一直在思考我实际上可以将什么以及多少放入替代变量中。我们可以只用它来替换单个 'entity' 而不是一串命令吗?我发现如果我想替换一块实际的 SQL,它不起作用(在 SqlDeveloper 中)。
我想知道如何解决这个问题...
/*------test--------------*/
CREATE TABLE Test_Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(1,'LN_1','FN_1');
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(2,'LN_2','FN_2');
INSERT INTO Test_Persons
(PersonID,LastName,FirstName)
values(3,'LN_21','FN_2');
commit;
--------------sub-table, worked!---
set define #;
define first_name_input = 'FN_2';
define last_name_input = 'LN_2';
define tbl_Test_Persons = 'Test_Persons';
define temp_tbl_Test_Persons_FN = 'Test_Persons_FN';
with
#temp_tbl_Test_Persons_FN as
(
select * from #tbl_Test_Persons tp
where tp.FIRSTNAME = '#first_name_input'
)
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input';
set define off;
--------------sub-table, replace the entire with clause, does NOT work - 'Invalid value for DEFINE command.'!---
set define #;
define first_name_input = 'FN_2';
define last_name_input = 'LN_2';
define tbl_Test_Persons = 'Test_Persons';
define temp_tbl_Test_Persons_FN = 'Test_Persons_FN2';
define with_clause = '
with
#temp_tbl_Test_Persons_FN as
(
select * from #tbl_Test_Persons tp
where tp.FIRSTNAME = ''#first_name_input''
)
';
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input';
set define off;
From the documentation(对于 SQL*Plus 但也适用于 SQL 开发人员):
If the value of a defined variable extends over multiple lines (using the SQL*Plus command continuation character), SQL*Plus replaces each continuation character and carriage return with a space.
SQL 开发人员的行为 略有 不同,并将继续字符留在字符串中,这没有帮助。但是它也留下了换行符,所以你可以将连续字符从 -
加倍到 --
以阻止它引起问题,因为它随后被视为注释;所以你可以这样做:
define with_clause = '--
with--
#temp_tbl_Test_Persons_FN as--
(--
select * from #tbl_Test_Persons tp--
where tp.FIRSTNAME = ''#first_name_input''--
)--
';
但还有一个更复杂的问题,因为 #with_clause
未被识别为命令 - 因为您尚未进入命令替换不会发生。您可以使用子查询来解决这个问题:
select * from (
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input'
);
这并不理想。但是,如果您这样做,脚本输出 window 会显示正在发生的替换,并且您会返回一行:
old:select * from (
#with_clause
select * from #temp_tbl_Test_Persons_FN tp
where tp.LASTNAME = '#last_name_input'
)
new:select * from (
--
with--
Test_Persons_FN2 as--
(--
select * from Test_Persons tp--
where tp.FIRSTNAME = 'FN_2'--
)--
select * from Test_Persons_FN2 tp
where tp.LASTNAME = 'LN_2'
)
PERSONID LASTNAME FIRSTNAME
---------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 LN_2 FN_2
(此外,有趣的是,这在 SQL 中仍然不起作用*另外,如果您使用 #
作为替换字符 - 您会得到 "ORA-24333: zero iteration count"。它不会得到&
的那个错误;我还没有尝试过任何其他的。你必须回到单个连接字符。但即使进行了这些更改,它仍然不能正确地替换 with
子句。还不确定为什么。)