在过程中重复使用 Select 语句
Reuse Select Statement within a Procedure
我喜欢做类似的事情
create tmp_table as ( select 1 some_value, 2 some_other_value from dual union select 3 some_value, 4 some_other_value from dual );
insert into table1 (field1) select some_value from tmp_table;
update table2 set field2 = 5 where field1 in ( select some_value from tmp_table );
drop tmp_table;
有更好的方法吗?也许是 WITH 语句的迭代使用?
with tmp_statement as (select ...) ( insert... update ... )
编辑:
您好,很抱歉提出一个非常笼统的问题。基本上,我想改进一些公司语法(select..loop...在这里逐行慢慢地做事)通过拆分操作但保持“一个 select only”规则有效,因为select 会很庞大,无论如何您只想编辑一个 select。我尝试使用 with 因为它看起来更接近现有语法。但也许将 select 加载到 temp/private/actual table 中的功能是更好的方法。
谢谢大家!
如果您正在寻找一种纯粹的 SQL 解决方案来跨多个语句引用一个值,请使用替换变量(适用于 SQL*Plus,SQL Developer, sqlcl 和任何其他支持 SQL*Plus 命令的环境):
ACCEPT some_value PROMPT "Please enter a value for SOME_VALUE:"
insert into table1 (field1) select '&&some_value' from dual;
update table2 set field2 = 5 where field1 in ('&&some_value' );
但是,您对 set-based 操作的使用表明您期望 TMP_TABLE 可能包含不止一行。以上在那种情况下不起作用。如果是这种情况,请编辑您的问题以提供有关您要实现的目标的更多详细信息。
对此有多种解决方案,其中包括 PL/SQL 集合或跨执行保留 TMP_TABLE。这取决于你想多久做一次。
创建和删除像 TMP_TABLE 这样的对象的 anti-pattern 在具有 T-SQL 背景的开发人员中很常见。 Oracle 在几个方面与 SQL Server 不同,这就是其中之一:作为某些事务逻辑的一部分,它不赞成动态执行 DDL。
可能您需要的方法是将 TMP_TABLE 创建为全局临时 TABLE。这是一个永久数据结构,但它的数据在事务(或会话)结束时被丢弃。如果您选择这种方法,您将创建 TMP_TABLE 一次,然后在需要时使用它,而不会在每个会话结束时删除。 Find out more.
如果您使用的是 Oracle 18c 或更高版本,您可以使用新的 private temporary tables
在您的特定情况下,您可以创建私有 table,然后进行插入和更新、提交和退出。私有临时 table 可以是特定于事务或特定于会话的。
考虑参数 PRIVATE_TEMP_TABLE_PREFIX
的值,它决定了名称约定的前缀
create private temporary table ora$ptt_tmp_table on commit drop definition
as select 1 as some_value from dual ;
insert into table1 (field1) select some_value from ora$ptt_tmp_table ;
update table2 set field2 = 5 where field1 in ( select some_value from ora$ptt_tmp_table );
commit ; -- here the private table is dropped automatically
您没有发布足够的详细信息,所以我会尝试列出所有变体:
如果您只需要几个变量,那么您有以下选择:
- 替换变量 (&var)
- PL/SQL 变量,不同的可用范围,例如局部变量,私有或 public 包变量,甚至 objects
- Collections:嵌套tables或varrays,例如:
- 变量数组:
select * from table(sys.odcivarchar2list('a','b','c'));
- 嵌套 table:
select * from table(sys.ku$_vcnt('a','b','c'));
- 嵌套 table 个数字对:
select *
from
table(
sys.ku$_objnumpairlist(
ku$_objnumpair(1,2),
ku$_objnumpair(3,4)));
NUM1 NUM2
---------- ----------
1 2
3 4
- 上下文变量,例如:
SQL> call DBMS_SESSION.SET_CONTEXT('CLIENTCONTEXT', 'var1', 'value1');
Call completed.
SQL> select SYS_CONTEXT('CLIENTCONTEXT', 'var1') as var1 from dual;
VAR1
-----------------
value1
- 如果需要存储数据集(行集):
- 全局临时tables(甚至私有临时表(18c+))
- Collections
我喜欢做类似的事情
create tmp_table as ( select 1 some_value, 2 some_other_value from dual union select 3 some_value, 4 some_other_value from dual );
insert into table1 (field1) select some_value from tmp_table;
update table2 set field2 = 5 where field1 in ( select some_value from tmp_table );
drop tmp_table;
有更好的方法吗?也许是 WITH 语句的迭代使用?
with tmp_statement as (select ...) ( insert... update ... )
编辑:
您好,很抱歉提出一个非常笼统的问题。基本上,我想改进一些公司语法(select..loop...在这里逐行慢慢地做事)通过拆分操作但保持“一个 select only”规则有效,因为select 会很庞大,无论如何您只想编辑一个 select。我尝试使用 with 因为它看起来更接近现有语法。但也许将 select 加载到 temp/private/actual table 中的功能是更好的方法。
谢谢大家!
如果您正在寻找一种纯粹的 SQL 解决方案来跨多个语句引用一个值,请使用替换变量(适用于 SQL*Plus,SQL Developer, sqlcl 和任何其他支持 SQL*Plus 命令的环境):
ACCEPT some_value PROMPT "Please enter a value for SOME_VALUE:"
insert into table1 (field1) select '&&some_value' from dual;
update table2 set field2 = 5 where field1 in ('&&some_value' );
但是,您对 set-based 操作的使用表明您期望 TMP_TABLE 可能包含不止一行。以上在那种情况下不起作用。如果是这种情况,请编辑您的问题以提供有关您要实现的目标的更多详细信息。
对此有多种解决方案,其中包括 PL/SQL 集合或跨执行保留 TMP_TABLE。这取决于你想多久做一次。
创建和删除像 TMP_TABLE 这样的对象的 anti-pattern 在具有 T-SQL 背景的开发人员中很常见。 Oracle 在几个方面与 SQL Server 不同,这就是其中之一:作为某些事务逻辑的一部分,它不赞成动态执行 DDL。
可能您需要的方法是将 TMP_TABLE 创建为全局临时 TABLE。这是一个永久数据结构,但它的数据在事务(或会话)结束时被丢弃。如果您选择这种方法,您将创建 TMP_TABLE 一次,然后在需要时使用它,而不会在每个会话结束时删除。 Find out more.
如果您使用的是 Oracle 18c 或更高版本,您可以使用新的 private temporary tables
在您的特定情况下,您可以创建私有 table,然后进行插入和更新、提交和退出。私有临时 table 可以是特定于事务或特定于会话的。
考虑参数 PRIVATE_TEMP_TABLE_PREFIX
的值,它决定了名称约定的前缀
create private temporary table ora$ptt_tmp_table on commit drop definition
as select 1 as some_value from dual ;
insert into table1 (field1) select some_value from ora$ptt_tmp_table ;
update table2 set field2 = 5 where field1 in ( select some_value from ora$ptt_tmp_table );
commit ; -- here the private table is dropped automatically
您没有发布足够的详细信息,所以我会尝试列出所有变体:
如果您只需要几个变量,那么您有以下选择:
- 替换变量 (&var)
- PL/SQL 变量,不同的可用范围,例如局部变量,私有或 public 包变量,甚至 objects
- Collections:嵌套tables或varrays,例如:
- 变量数组:
select * from table(sys.odcivarchar2list('a','b','c'));
- 嵌套 table:
select * from table(sys.ku$_vcnt('a','b','c'));
- 嵌套 table 个数字对:
- 变量数组:
select *
from
table(
sys.ku$_objnumpairlist(
ku$_objnumpair(1,2),
ku$_objnumpair(3,4)));
NUM1 NUM2
---------- ----------
1 2
3 4
- 上下文变量,例如:
SQL> call DBMS_SESSION.SET_CONTEXT('CLIENTCONTEXT', 'var1', 'value1');
Call completed.
SQL> select SYS_CONTEXT('CLIENTCONTEXT', 'var1') as var1 from dual;
VAR1
-----------------
value1
- 如果需要存储数据集(行集):
- 全局临时tables(甚至私有临时表(18c+))
- Collections