【问题标题】:Oracle trigger not inserting values in another tableOracle触发器不在另一个表中插入值
【发布时间】:2015-11-25 14:17:09
【问题描述】:

我有SOAP_SERVICE 表,如果新值被插入到这个表中,那么这些值也应该插入到SOAP_SERVICE_STATUS 表中。我正在为此编写下面的触发器,它没有任何错误并成功编译。但是当我尝试将值插入到SOAP_SERVICE 表中时,该值没有插入到SOAP_SERVICE_STATUS 表中。

create or replace TRIGGER RATOR_MONITORING.TRG_TRK_SOAP_SERVICE_STATUS
  AFTER INSERT 
 ON RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE
 FOR EACH ROW
BEGIN
   INSERT INTO RATOR_MONITORING.SOAP_SERVICE_STATUS (SOAP_SERVICE_STATUS_ID,SOAP_SERVICE_ID,STATUS)
       VALUES (SOAP_SERVICE_STATUS_SEQ.nextval,:new.SOAP_SERVICE_ID,'N');
END;

【问题讨论】:

  • 我认为我的触发器是正确的,唯一的问题是提交..

标签: oracle triggers insert


【解决方案1】:

抱歉,这个无法重现:

SQL> CREATE USER RATOR_MONITORING IDENTIFIED BY "password"
2            DEFAULT TABLESPACE USERS;

User created.

SQL> CREATE USER RATOR_MONITORING_CONFIGURATION IDENTIFIED BY "password"
2            DEFAULT TABLESPACE USERS;

User created.

SQL> GRANT CONNECT TO RATOR_MONITORING, RATOR_MONITORING_CONFIGURATION;

Grant succeeded.

SQL> GRANT CREATE TABLE TO RATOR_MONITORING, RATOR_MONITORING_CONFIGURATION;

Grant succeeded.

SQL> GRANT CREATE SEQUENCE TO RATOR_MONITORING;

Grant succeeded.

SQL> GRANT CREATE ANY TRIGGER TO RATOR_MONITORING;

Grant succeeded.

SQL> ALTER USER RATOR_MONITORING QUOTA UNLIMITED ON USERS;

User altered.

SQL> ALTER USER RATOR_MONITORING_CONFIGURATION QUOTA UNLIMITED ON USERS;

User altered.

SQL> CONNECT RATOR_MONITORING_CONFIGURATION/password
Connected.
SQL> CREATE TABLE RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE (SOAP_SERVICE_ID INTEGER);

Table created.

SQL> CONNECT RATOR_MONITORING/password
Connected.
SQL> CREATE TABLE RATOR_MONITORING.SOAP_SERVICE_STATUS
2              (SOAP_SERVICE_STATUS_ID INTEGER, SOAP_SERVICE_ID INTEGER, STATUS CHAR(1));

Table created.

SQL> CREATE SEQUENCE RATOR_MONITORING.SOAP_SERVICE_STATUS_SEQ;

Sequence created.

SQL> create or replace TRIGGER RATOR_MONITORING.TRG_TRK_SOAP_SERVICE_STATUS
2       AFTER INSERT
3      ON RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE
4      FOR EACH ROW
5     BEGIN
6        INSERT INTO RATOR_MONITORING.SOAP_SERVICE_STATUS (SOAP_SERVICE_STATUS_ID,SOAP_SERVICE_ID,STATUS)
7            VALUES (SOAP_SERVICE_STATUS_SEQ.nextval,:new.SOAP_SERVICE_ID,'N');
8     END;
9     /

Trigger created.

SQL> CONNECT RATOR_MONITORING_CONFIGURATION/password
Connected.
SQL> INSERT INTO RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE (SOAP_SERVICE_ID) VALUES (7);

1 row created.

SQL> COMMIT;

Commit complete.

SQL> CONNECT RATOR_MONITORING/password
Connected.
SQL> SELECT * FROM RATOR_MONITORING.SOAP_SERVICE_STATUS;

SOAP_SERVICE_STATUS_ID SOAP_SERVICE_ID S
---------------------- --------------- -
                     1               7 N

注意事项:

  1. CREATE ANY TRIGGER 权限是RATOR_MONITORING 在另一个架构中的表上创建触发器所必需的,
  2. 当我们在 SQL*Plus 中更改连接时,数据库会创建一个新会话供我们使用。在提交这些更改之前,在一个会话中所做的更改在另一个会话中不可见。
  3. SQL*Plus 在断开连接时隐式提交事务。在上面的示例中,我们在最后一个 CONNECT 之前显式提交,因此我们不依赖于隐式行为。

【讨论】:

  • 漂亮而完整的例子;我慢了几分钟:);但是我要完全证明您应该与创建的用户连接(而不是使用 SYS)。结果是用户 RATOR_MONITORING_CONFIGURATION 没有对 RATOR_MONITORING.SOAP_SERVICE_STATUS 进行 SELECT 授权。与 RATOR_MONITORING 的连接(没有提交)会给出一个空表。
  • @MarmiteBomber:这是一个公平的观点,我已经更新了脚本以连接相关用户。
  • 我认为我的触发器是正确的,唯一的问题是提交。我无法在触发器中提供提交,它会给出错误。所以我每次都必须明确使用提交对吗?
  • @Rahul - 这是一个标准的事务逻辑。使用触发器在表中插入记录的会话可以从 两个 表中选择数据(前提是它具有 SELECT 权限)。并且在您提交事务之前,两个 表中的新记录对于其他会话是不可见的。您提交的频率取决于您的应用程序逻辑,例如如果其他会话应该看到每条新记录,则必须在每次插入后提交。
【解决方案2】:

最可能的解释是您选择了具有不同连接的表RATOR_MONITORING.SOAP_SERVICE_STATUS,而没有提交在RATOR_MONITORING_CONFIGURATION.SOAP_SERVICE 中执行插入的原始会话。 提交后记录应该是可见的。

还请注意,这是触发器与表位于不同架构这一事实的副作用;用户 RATOR_MONITORING_CONFIGURATION 可以在表中插入 RATOR_MONITORING.SOAP_SERVICE_STATUS,即使他/她没有 INSERT 授权!

要启用此功能,用户 RATOR_MONITORING 必须具有特权 create any trigger - 这并不总是被认为是最佳实践(至于强大的特权) - 参见例如 Tom Kyte

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多