“错误:输入结束时的语法错误”运行时命令

发布于 2025-02-09 07:28:14 字数 424 浏览 1 评论 0原文

我试图创建一个日历表。以下查询。我在标题中得到错误。有人可以解释为什么吗?

create table if not exists test_calendar (test_date date primary key);

do $$
declare
    i intEGER := 0 ;--, date datetime := '20090101';
Begin
    while i <= 10 loop
        begin
            insert into test_calendar (test_date) values (dateadd(dd,i,'20090101'));
            i := i + 1;
        end;
    end Loop;
$$ ;

SELECT * FROM test_calendar

I was trying to create a calendar table. The query below. I get the error in the title. Can someone explain why?

create table if not exists test_calendar (test_date date primary key);

do $
declare
    i intEGER := 0 ;--, date datetime := '20090101';
Begin
    while i <= 10 loop
        begin
            insert into test_calendar (test_date) values (dateadd(dd,i,'20090101'));
            i := i + 1;
        end;
    end Loop;
$ ;

SELECT * FROM test_calendar

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

怪我鬧 2025-02-16 07:28:14

错误消息的直接原因是最后一个缺少结束

DO
$do$
DECLARE
   i int := 0;
   _date date := '2009-01-01';
BEGIN
   WHILE i <= 10 LOOP
      BEGIN  -- expensive noise
         INSERT INTO test_calendar (test_date)
         VALUES (_date + i);
         i := i + 1;
      END;
   END LOOP;
END  -- !
$do$;

最终结束之后的分号是可选的。

但是还有更多:

DO
$do$
DECLARE
   _date date := '2009-01-01';
BEGIN
   FOR i IN 1..10  -- i defined implicitely
   LOOP
      INSERT INTO test_calendar (test_date)
      VALUES (_date + i);
   END LOOP;
END
$do$;

上面的所有方法

都是概念的证明。我真正会做的是:

INSERT INTO test_calendar (test_date)
SELECT generate_series(timestamp '2009-01-01'
                     , timestamp '2009-01-11'
                     , interval '1 day');

db&lt; em>

基于设定的解决方案通常对此更好。在Postgres中使用generate_series()。详细说明:

单个多行插入比许多单行 insert 命令便宜得多。

分配中生成的timestamp值将date施加到。在其他情况下,您可能需要明确施放。

通常,您甚至根本不需要持久的日历表。只需直接使用generate_series()。可能甚至更快。

The immediate cause of the error message is the missing END at the end.

DO
$do$
DECLARE
   i int := 0;
   _date date := '2009-01-01';
BEGIN
   WHILE i <= 10 LOOP
      BEGIN  -- expensive noise
         INSERT INTO test_calendar (test_date)
         VALUES (_date + i);
         i := i + 1;
      END;
   END LOOP;
END  -- !
$do$;

A semicolon after the final END is optional.

But there is more:

  • There is no dateadd() function in Postgres (like in SQL Server). You can simply add integer to a date for your purpose.

  • The expensive nested block serves no purpose. Remove it.

  • Such a loop is simpler and cheaper with FOR. See:

DO
$do$
DECLARE
   _date date := '2009-01-01';
BEGIN
   FOR i IN 1..10  -- i defined implicitely
   LOOP
      INSERT INTO test_calendar (test_date)
      VALUES (_date + i);
   END LOOP;
END
$do$;

Proper way

All of the above is just proof of concept. What I really would do:

INSERT INTO test_calendar (test_date)
SELECT generate_series(timestamp '2009-01-01'
                     , timestamp '2009-01-11'
                     , interval '1 day');

db<>fiddle here

A set-based solution is generally better for this. Use generate_series() in Postgres. Detailed explanation:

A single multi-row INSERT is much cheaper than many single-row INSERT commands.

The generated timestamp values are cast to date in the assignment. In other contexts you may need to cast explicitly.

Typically, you don't even need a persisted calendar table at all in Postgres. Just use generate_series() directly. Might be even faster.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文