【问题标题】:Store PL/SQL Statement in a CLOB value, escape characters not working将 PL/SQL 语句存储在 CLOB 值中,转义字符不起作用
【发布时间】:2017-06-11 02:14:31
【问题描述】:

我有这个语句,它在 CLOB 中插入一些信息和一个完整的触发器。但是,我收到此错误:ORA-01756: quoted string not properly terminated

我在触发器的每个引号前添加了转义字符 (')。但是我不明白为什么我不断收到此错误。

这是表创建查询:

CREATE TABLE Template (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), triggerEvent clob NOT NULL, triggerCode clob NOT NULL, TemplateTypeid number(10) NOT NULL, PRIMARY KEY (id));

这是整个插入查询:

drop table template CASCADE CONSTRAINTS PURGE;
drop table TemplateType CASCADE CONSTRAINTS PURGE;
drop table BusinessRuleType CASCADE CONSTRAINTS PURGE;
drop table Operator CASCADE CONSTRAINTS PURGE;
drop table Category CASCADE CONSTRAINTS PURGE;
drop table BusinessRule CASCADE CONSTRAINTS PURGE;
drop table TargetDatabase CASCADE CONSTRAINTS PURGE;
drop table BusinessRuleType_Operator CASCADE CONSTRAINTS PURGE;
drop table DatabaseType CASCADE CONSTRAINTS PURGE;
drop table RuleValues CASCADE CONSTRAINTS PURGE;
drop sequence ARNG_seq;

CREATE SEQUENCE ARNG_seq;

CREATE TABLE Template (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), triggerEvent clob NOT NULL, triggerCode clob NOT NULL, TemplateTypeid number(10) NOT NULL, PRIMARY KEY (id));
CREATE TABLE TemplateType (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), category varchar2(255) NOT NULL, DatabaseTypeid number(10) NOT NULL, PRIMARY KEY (id));
CREATE TABLE BusinessRuleType (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), name varchar2(255), Categoryid number(10) NOT NULL, Templateid number(10) NOT NULL, PRIMARY KEY (id));
CREATE TABLE Operator (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 5), operatorType varchar2(255) NOT NULL, name varchar2(255) NOT NULL, value varchar2(255) NOT NULL, PRIMARY KEY (id));
CREATE TABLE Category (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), name varchar2(255) NOT NULL, PRIMARY KEY (id));
CREATE TABLE BusinessRule (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), generatedCode clob, name varchar2(255) NOT NULL, errorMessage varchar2(255) NOT NULL, validationFailureSeverity varchar2(50) NOT NULL, targetColumn varchar2(255) NOT NULL, targetTable varchar2(255) NOT NULL, BusinessRuleTypeid number(10) NOT NULL, SavedTargetDatabaseid number(10) NOT NULL, Operatorid number(10) NOT NULL, PRIMARY KEY (id));
CREATE TABLE TargetDatabase (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), name varchar2(255) NOT NULL, url varchar2(255) NOT NULL, username varchar2(255) NOT NULL, password varchar2(255) NOT NULL, DatabaseTypeid number(10) NOT NULL, PRIMARY KEY (id));
CREATE TABLE BusinessRuleType_Operator (BusinessRuleTypeid number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), Operatorid number(10) NOT NULL, PRIMARY KEY (BusinessRuleTypeid, Operatorid));
CREATE TABLE DatabaseType (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), databaseType varchar2(255) NOT NULL, PRIMARY KEY (id));
CREATE TABLE RuleValues (id number(10) GENERATED BY DEFAULT ON NULL AS IDENTITY (START WITH 2), name varchar2(255) NOT NULL, stringValue varchar2(255), intValue number(10), clobValue clob, BusinessRuleid number(10) NOT NULL, PRIMARY KEY (id));
ALTER TABLE BusinessRuleType ADD CONSTRAINT FKBusinessRu863439 FOREIGN KEY (Categoryid) REFERENCES Category (id);
ALTER TABLE BusinessRule ADD CONSTRAINT FKBusinessRu277804 FOREIGN KEY (BusinessRuleTypeid) REFERENCES BusinessRuleType (id);
ALTER TABLE BusinessRuleType ADD CONSTRAINT FKBusinessRu443116 FOREIGN KEY (Templateid) REFERENCES Template (id);
ALTER TABLE Template ADD CONSTRAINT FKTemplate586491 FOREIGN KEY (TemplateTypeid) REFERENCES TemplateType (id);
ALTER TABLE BusinessRuleType_Operator ADD CONSTRAINT FKBusinessRu447733 FOREIGN KEY (BusinessRuleTypeid) REFERENCES BusinessRuleType (id);
ALTER TABLE BusinessRuleType_Operator ADD CONSTRAINT FKBusinessRu382431 FOREIGN KEY (Operatorid) REFERENCES Operator (id);
ALTER TABLE BusinessRule ADD CONSTRAINT FKBusinessRu873463 FOREIGN KEY (SavedTargetDatabaseid) REFERENCES TargetDatabase (id);
ALTER TABLE TemplateType ADD CONSTRAINT FKTemplateTy236989 FOREIGN KEY (DatabaseTypeid) REFERENCES DatabaseType (id);
ALTER TABLE TargetDatabase ADD CONSTRAINT FKTargetData209438 FOREIGN KEY (DatabaseTypeid) REFERENCES DatabaseType (id);
ALTER TABLE BusinessRule ADD CONSTRAINT FKBusinessRu447639 FOREIGN KEY (Operatorid) REFERENCES Operator (id);
ALTER TABLE RuleValues ADD CONSTRAINT FKRuleValues255277 FOREIGN KEY (BusinessRuleid) REFERENCES BusinessRule (id);


INSERT INTO Category (id, name) VALUES (1, 'Static');
INSERT INTO Category (id, name) VALUES (2, 'Dynamic');

INSERT INTO Operator (id, operatortype, name, value) VALUES (1, 'Compare', 'Equals', '=');
INSERT INTO Operator (id, operatortype, name, value) VALUES (2, 'Compare', 'Not Equals', '!=');
INSERT INTO Operator (id, operatortype, name, value) VALUES (3, 'Range', 'Between', 'BETWEEN');
INSERT INTO Operator (id, operatortype, name, value) VALUES (4, 'Range', 'Not Between', 'NOTBETWEEN');


INSERT INTO DatabaseType (id, databaseType) VALUES (1, 'Oracle');

INSERT INTO TargetDatabase (id, name, url, username, password, DatabaseTypeid) VALUES (1, 'School Database', 'XXXX', 'XXX', 'XX', 1);

INSERT INTO TemplateType (id, category, DatabaseTypeid) VALUES (1, 'Constraint', 1);

INSERT INTO Template (id, triggerevent, triggercode, templatetypeid) VALUES (1, 'insert, update <<column>> | <<table>>', q'[CREATE OR REPLACE TRIGGER BRG_{code}_{attribute_table}_TRG
BEFORE DELETE OR INSERT OR UPDATE
ON {attribute_table}
FOR EACH ROW
DECLARE
  L_OPER        VARCHAR2(3);
  L_ERROR_STACK VARCHAR2(4000);
BEGIN
  IF INSERTING
  THEN
    L_OPER := 'INS';
  ELSIF UPDATING
    THEN
      L_OPER := 'UPD';
  ELSIF DELETING
    THEN
      L_OPER := 'DEL';
  END IF;
  DECLARE
    L_PASSED BOOLEAN := TRUE;
  BEGIN
    IF L_OPER IN ('INS', 'UPD')
    THEN
      IF '{operand}' = '=' THEN
        L_PASSED := :NEW.{attribute_column} >= {range_min} AND :NEW.{attribute_column} <= {range_max};
      ELSE
        L_PASSED := :NEW.{attribute_column} < {range_min} OR :NEW.{attribute_column} > {range_max};
      END IF;

      IF NOT L_PASSED
      THEN
        raise_application_error(-20000, {error});
      END IF;
    END IF;
  END;
END;]' , 1 );


INSERT INTO BusinessRuleType (id, name, categoryid, templateid) VALUES (1, 'Attribute Range Rule', 1, 1);
INSERT INTO BusinessRule (id, name, errorMessage, validationFailureSeverity, targetColumn, targetTable, BusinessRuleTypeid, SavedTargetDatabaseid, Operatorid) VALUES (1, 'BRG_NMR_CNS_RNG_01', 'Zit niet in de range', 'Informational Warning', 'cijfer', 'rapport', 1, 1, 1);

INSERT INTO RuleValues (id, name, intValue, BusinessRuleid) VALUES (1, 'MinValue', 1, 1);
INSERT INTO RuleValues (id, name, intValue, BusinessRuleid) VALUES (2, 'MaxValue', 10, 1);

INSERT INTO BusinessRuleType_operator (businessruletypeid, operatorid) VALUES (1,1);

我需要将整个触发器作为 CLOB 保存在数据库中的原因是因为我的 Java 后端可以使用它。

【问题讨论】:

    标签: sql oracle plsql triggers insert


    【解决方案1】:

    对于这种引用机制,我更喜欢使用 q'~blbelbe~' - ~ 是非常罕见的字符。

    您的问题在这里解决了 Oracle 12c 。 Text literals

    如果开头的quote_delimiter 是[、{、 或)。在所有其他情况下,开始和结束quote_delimiter 必须是相同的字符。

    【讨论】:

    • 是的,但它在 12c 中并不是新的。
    【解决方案2】:

    执行这两个语句没有问题。此外,您可以考虑使用 Q 字符来避免转义引号。如:

    q'[插入xxx个值('a', 'b', 'c')]'

    但正如我上面所说,据我所知,您发布的代码没有问题。

    CREATE TABLE template
    (
       id               NUMBER (10) 
           GENERATED BY DEFAULT ON NULL AS IDENTITY (       START WITH 2),
       triggerevent     CLOB NOT NULL,
       triggercode      CLOB NOT NULL,
       templatetypeid   NUMBER (10) NOT NULL,
       PRIMARY KEY (id)
    )
    /
    
    BEGIN
       INSERT INTO template (id,
                             triggerevent,
                             triggercode,
                             templatetypeid)
               VALUES (
                         1,
                         'insert, update <<column>> | <<table>>',
                         'CREATE OR REPLACE TRIGGER BRG_{code}_{attribute_table}_TRG
    BEFORE DELETE OR INSERT OR UPDATE
    ON {attribute_table}
    FOR EACH ROW
    DECLARE
      L_OPER        VARCHAR2(3);
      L_ERROR_STACK VARCHAR2(4000);
    BEGIN
      IF INSERTING
      THEN
        L_OPER := ''INS'';
      ELSIF UPDATING
        THEN
          L_OPER := ''UPD'';
      ELSIF DELETING
        THEN
          L_OPER := ''DEL'';
      END IF;
      DECLARE
        L_PASSED BOOLEAN := TRUE;
      BEGIN
        IF L_OPER IN (''INS'', ''UPD'')
        THEN
          IF ''{operand}'' = ''BETWEEN'' THEN
            L_PASSED := :NEW.{attribute_column} >= {range_min} AND :NEW.{attribute_column} <= {range_max};
          ELSE
            L_PASSED := :NEW.{attribute_column} < {range_min} OR :NEW.{attribute_column} > {range_max};
          END IF;
    
          IF NOT L_PASSED
          THEN
            raise_application_error(-20000, {error});
          END IF;
        END IF;
      END;
    END;',
                         1);
    END;
    

    【讨论】:

    • 感谢您花时间运行它。但是,它仍然给我一个错误(即使使用 q[] 语句)。我已经编辑了我的初始帖子,向您展示了我正在尝试运行的完整脚本。如果您能解决这个问题,我将不胜感激。
    • 我确实运行了你的代码。然而它仍然给我们一个错误,关于期待一个 INSERT 语句的东西。我们通过使 clob 可以为空来解决该问题,并在文件末尾将其插入到模板中(有点像贫民窟的解决方案,但这是我们能够解决的唯一方法)。您是否尝试过运行我添加到主帖中的整个文件?提前致谢。
    • “关于期待 INSERT 语句的事情”,认真的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多