如何在更新另一个表后自动在表中创建行

时间:2016-01-21 03:44:54

标签: sql

我正在开发一个Web应用程序。在Web应用程序的数据库中,我有一个名为Daily的表,我每天都在这个表中输入。让我们说它有3列A,B和C.我有另一个名为Monthly的表,其中我每月存储相同的A,B,C值。现在我想要的是,当一个月完成时,即每日表中的条目没有变为30或31,那么在每月表中自动创建一个新行,其A,B和C值将包含每日表中所有值的总和。相应的A,B,C值。 我想知道如何使用SQL来实现这一点,如果没有,还有什么方法可以做到这一点?

1 个答案:

答案 0 :(得分:0)

根据您的数据库,操作系统,编程语言等,Gordon Linoff的回应可能是一个很好的方法。

另一种方法是在Daily表上创建一个“触发器”,当插入该月的最后一天的行时,它会自动执行汇总。请注意:触发器很棘手,可能会使维护和复制变得复杂。

为了使解释更容易,我会更具体一点。此外,语法的细节将取决于您具体选择的数据库。这个答案将使用PostgreSQL语法。

这是每日表。我添加了一个列来包含日期,并将其作为主键。

CREATE TABLE daily
(
  daily_date date NOT NULL,
  a integer NOT NULL,
  b integer NOT NULL,
  c integer NOT NULL,
  CONSTRAINT daily_pkey PRIMARY KEY (daily_date)
);

这是月度表:

CREATE TABLE monthly
(
  monthly_date date NOT NULL,
  a_sum integer NOT NULL,
  b_sum integer NOT NULL,
  c_sum integer NOT NULL,
  CONSTRAINT monthly_pkey PRIMARY KEY (monthly_date)
);

现在我们创建一个在插入月份的最后一个每日行时调用的过程。在PostgreSQL中,这是一种称为触发器函数的特殊类型。细节因您的数据库而异。

CREATE OR REPLACE FUNCTION summarize_month()
  RETURNS trigger AS
$BODY$DECLARE 
    month_begin DATE :=
        make_date(
            cast (extract(year from new.daily_date) as integer),
            cast (extract(month from new.daily_date) as integer),
            1);
    month_end DATE :=   
        month_begin + interval '1 month' - interval '1 day';
BEGIN
    INSERT INTO monthly(monthly_date, a_sum, b_sum, c_sum)
    (SELECT month_begin, sum(a), sum(b),sum(c)
    FROM daily
    WHERE daily_date BETWEEN month_begin AND month_end);
    return null;

END;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

此过程根据刚刚插入的行的daily_date计算要汇总的月份的开始和结束日期。然后,它会在monthly表中插入一个新行,其中包含SELECT语句计算的汇总数据。

最后,我们将触发器函数附加到daily表,并告诉它仅在插入月份最后一天的行时执行。

CREATE TRIGGER summarize_daily_to_monthly
  AFTER INSERT
  ON daily
  FOR EACH ROW
  WHEN ((date_part('month'::text, new.daily_date) <> 
         date_part('month'::text, (new.daily_date + 1))))
  EXECUTE PROCEDURE summarize_month();

我知道这听起来像一个简单的问题是一个很长的答案。如果您需要进一步澄清,请随时询问。