繁体   English   中英

PL / SQL过程语法

[英]PL/SQL Procedure Syntax

因此,我在使用某些PL SQL语句时遇到了一些麻烦。 本质上,我正在尝试创建一个过程,该过程将检查是否在插入新的元组时检查在同一日期(即同一个人)是否没有其他合同。 新合同的日期不得与其他合同的日期重叠。

这是代码:

CREATE OR REPLACE PROCEDURE dateOrder 
(name IN VARCHAR2, start IN DATE, end IN DATE)
IS 
    x number;
    y number;

BEGIN
    CREATE OR REPLACE VIEW PersonContracts AS
    SELECT * FROM ContractInfo WHERE HasContract=name;

    SELECT COUNT(*) INTO x FROM PersonContracts
    WHERE start BETWEEN date_from AND date_to;

    SELECT COUNT(*) INTO y from PersonContracts
    WHERE end BETWEEN date_from AND date_to;
    IF x > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;

    IF Y > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;

END dateOrder;
/

BEGIN
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014");
END;

我尝试过有或没有视图,但如果可能的话,我希望保留视图。 我只是PL的新手!

您不能在使用DDL的过程中创建VIEW(您必须使用EXECUTE IMMEDIATE这样做)。

我希望直接设置SELECT语句的WHERE-Clause:

CREATE OR REPLACE PROCEDURE dateOrder (name IN VARCHAR2, start IN DATE, end IN DATE)
    IS 
       x number;
       y number;
    BEGIN

    SELECT COUNT(*) INTO x FROM ContractInfo WHERE HasContract=name
    AND start BETWEEN date_from AND date_to;

    SELECT COUNT(*) INTO y from ContractInfo WHERE HasContract=name
    AND end BETWEEN date_from AND date_to;

    IF x > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;

    IF Y > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;

END dateOrder;
/

BEGIN
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014");
END;

因此,有些事情在您的程序中不起作用。 将此作为建议而不是解决方案:

  1. 在过程中编写ddl并不是一种好的样式。 顺便说一下,在此过程中访问新视图是不可能的!
  2. 如果要这样做,请将Create View放入动态SQL语句中,如下面的代码段所示
  3. 您要从过程中访问的所有DB对象都必须在编译时存在。 因此,除非您也使用动态SQL编写所有Select语句,否则此代码将永远无法工作。
  4. 不要将参数命名为“开始”或“结束”。 Theese是保留字,因此是不允许的。
  5. 如果调用dateOrder过程,请确保将有效日期作为参数传递。 在您的示例中,您将传递字符串。 也许这将与您的默认NLS一起使用,但在其他环境/数据库中可能无法使用。

看一下这个:

CREATE OR REPLACE PROCEDURE dateOrder
(name IN VARCHAR2, xstart IN DATE, xend IN DATE)
IS
    x number;
    y number;

BEGIN
    execute immediate (
      'CREATE OR REPLACE VIEW PersonContracts AS
      SELECT * FROM ContractInfo ....'
    );
    -- that won't work, because the PersonContracts will be not there at compile time.
    SELECT COUNT(*) INTO x FROM PersonContracts
    WHERE start BETWEEN date_from AND date_to;

    SELECT COUNT(*) INTO y from PersonContracts
    WHERE end BETWEEN date_from AND date_to;
    IF x > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;

    IF Y > 0 THEN
        dbms_output.put_line("overlaps.");
    END IF;


END dateOrder;


BEGIN
    dateOrder("John Smith", "08-oct-2014", "12-oct-2014");
END;

即使允许视图也不必要。 您只想检查HasContract值等于name参数的行。 好的,根据需要编写查询,然后将HasContract = name添加到where子句。 不要过度考虑简单的解决方案。

另外,您可以在一个查询中找到所需的内容。 您要捕获的条件是,由开始日期和结束日期定义的间隔与任何现有的开始日期和停止日期之间是否存在重叠。 虽然我们会尽力列出可能导致重叠的所有可能安排,但让我们看一下不会导致重叠的仅有的两种安排。

  • 如果一个的结束日期小于或等于另一个的开始日期,或者
  • 如果一个的开始日期大于或等于另一个的结束数据。

或者,以等式形式e1 <= s2 or s1 >= e2 一点点布尔魔术,我们可以求出e1 > s2 and s1 < e2 这给了我们简化的查询:

select COUNT(*) into y
from   ContractInfo
where  HasContract = name
  and  p_end   > date_from
  and  p_start < date_to;

如果此查询返回任何非零答案,则某处将存在重叠。 一个简单的查询,然后进行一次检查。 简单。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM