2

私はテーブルを持っていてaddress_all、それはいくつかのアドレステーブルに継承されています。address_history親テーブルから継承し、history_all現在のアドレス情報を保持します。テーブルを継承しaddress_all、情報を新しいテーブルにコピーする新しいテーブルを作成していaddress_historyます。

私のストアドプロシージャは次のようになります。呼び出すとエラーが発生します。エラーをよりよく説明するために、私は行番号を使用しています。

1  CREATE OR REPLACE FUNCTION somefunc()
2  RETURNS void AS
3  $BODY$
4  DECLARE
5   year_id INTEGER;
6   month_id INTEGER;
7   week_id INTEGER;
8   addresstablename text; 
9   backupdays text;
10 BEGIN
11  week_id := EXTRACT(DAY FROM TIMESTAMP 'now()');
12  month_id := EXTRACT(MONTH FROM TIMESTAMP 'now()');
13  year_id := EXTRACT(YEAR FROM TIMESTAMP 'now()');
14  addresstablename := 'address_history_' || week_id || '_' || month_id || '_' || year_id;
15  backupdays:= date_trunc('hour',CURRENT_TIMESTAMP - interval '7 days');
16  EXECUTE 'create table ' || addresstablename || '() INHERITS (address_all)';
17  EXECUTE 'insert into ' || addresstablename || ' select * from address_history where address_timestamp >= ' || backupdays || ''; --AS timestamp without time zone);  
18 END;
19 $BODY$
20 LANGUAGE 'plpgsql' VOLATILE;

私が走るとき:

select somefunc()

このエラーが発生します:

ERROR:  syntax error at or near "12"
LINE 1: ...story where address_timestamp >= 2012-07-31 12:00:00-0...
                                                         ^
QUERY:  insert into address_history_7_8_2012 select * from address_history where address_timestamp >= 2012-07-31 12:00:00-04
CONTEXT:  PL/pgSQL function "somefunc" line 14 at EXECUTE statement

 ********** Error **********

ERROR: syntax error at or near "12"
SQL state: 42601
Context: PL/pgSQL function "somefunc" line 14 at EXECUTE statement
4

3 に答える 3

6

この大幅に簡略化された形式を試してください。

CREATE OR REPLACE FUNCTION somefunc()
  RETURNS void AS
$func$
DECLARE
 addresstablename text := 'address_history_' || to_char(now(), 'FMDD_MM_YYYY');

BEGIN
 EXECUTE 
 'CREATE TABLE ' || addresstablename || '() INHERITS (address_all)';

 EXECUTE
 'INSERT INTO ' || addresstablename || '
  SELECT *
  FROM   address_history
  WHERE  address_timestamp >= $1'
 USING date_trunc('hour', now() - interval '7 days');

END
$func$ LANGUAGE plpgsql;

主なポイント:

  • 宣言時にplpgsqlで変数を割り当てることができます。コードを簡素化します。

  • to_char()日付をフォーマットするために使用します。はるかに簡単です。

  • now()同じことをCURRENT_TIMESTAMPします。

  • 現在のタイムスタンプが必要な場合は、引用符で囲まずに(引用符なしで)使用してください'now()'now()

  • USINGと一緒に句をEXECUTE使用すると、 timestamptotextとbackを変換する必要がなくなります。おそらく、あなたが行ったように引用の問題が発生する可能性があります。より速く、より簡単に、より安全に。

  • LANGUAGE plpgsqlplpgsqlはキーワードであり、引用符で囲まないでください。

  • CREATE TABLE IF NOT EXISTSPostgreSQL9.1以降で使用可能なテーブルがにすでに存在するかどうかを確認することをお勧めします。

于 2012-08-07T17:05:13.193 に答える
2

どうやらあなたはバックアップ日を引用する必要があります、さもなければそれはタイムスタンプを解析する場所からの文字列として見られません。

于 2012-08-07T16:27:53.683 に答える
1

文字列操作を使用してSQLを構築しているため、他の言語と同じようにすべてを適切に引用する必要があります。あなたが知りたいと思ういくつかの関数があります:

  • quote_ident:テーブル名などの識別子を引用します。
  • quote_literal:文字列リテラルとして使用する文字列を引用します。
  • quote_nullable:asquote_literalですが、NULLも適切に処理します。

このようなものはあなたをより良くサーバーします:

EXECUTE 'create table ' || quote_ident(addresstablename) || ...
EXECUTE 'insert into '  || quote_ident(addresstablename) || ... || quote_literal(backupdays) ...

あなたのquote_ident場合、電話は必要ありませんが、良い習慣です。

于 2012-08-07T17:07:32.927 に答える