2012-05-09 10 views
0

Postgresデータベースでデータをインポートした後、ODBCソースから入ってきたデータの一部を正規化する関数を実行します。 1つのフィールドは日付ですが、varcharとして入力されていますが、一部の行ではnullですので、日付型に変換しようとすると失敗します。私はそれを直接実行する場合、これは動作します日付変換に関連するエラーPostgresフォルダ内のテーブルを更新する

UPDATE "MyTable" SET "VisitDate" = to_char(DATE("VisitDate"), 'DD Mon YYYY') WHERE "VisitDate" <> ''; 

:私は、データが表示のみのために使用されるそれはあまり重要ではありませんが、私はそれが便利なフォーマットにする必要がありますので、私は、次のSQLを見つけ実現しましたSQLブラウザで、私は関数を実行するとき、それはこのことを言う:

ERROR: table row type and query-specified row type do not match 
DETAIL: Table has type character varying at ordinal position 6, but query expects text. 

to_char()機能は、テキストを返しますが、フィールドがvarchar型である(およびコンテンツにそれを与えられたので、私の知る限り、これは私はおそらく私が次のことをすることができると思った:

ALTER TABLE "MyTable" ALTER "VisitDate" TYPE "text"; 
UPDATE "MyTable" SET "VisitDate" = to_char(DATE("VisitDate"), 'DD Mon YYYY') WHERE "VisitDate" <> ''; 
ALTER TABLE "MyTable" ALTER "VisitDate" TYPE varchar(12); 

私が理解しているように、Postgresは一回のトランザクションですべてを実行するので、UPDATEの前にALTER命令が実行されていないため、同じエラーが発生します。

varchar(to_char(...etc))を使用しようとすると、varchar関数の内容について不平を言うだけです。

以下のコメントに続いて、その行だけを関数に入れようとしましたが、正常に機能するテーブル変更ステートメントがあれば、両方とも失敗します。

CREATE OR REPLACE FUNCTION at_ebc_alterscorescolumns() RETURNS void AS 
$BODY$ 
ALTER TABLE "MyTable" ALTER "Postcode" TYPE varchar(10); 
UPDATE "MyTable" SET "VisitDate" = to_char(DATE("VisitDate"), 'DD Mon YYYY') WHERE "VisitDate" <> ''; 
$BODY$ 
LANGUAGE sql VOLATILE 
COST 100; 

これは、テーブルを変更し、単一の関数内のデータを変更することはできません場合は、単にであるかどうかを疑問に私をリード:機能の基本的な形は、これがあります。

私の質問は次のとおりです。このエラーを発生させずにフィールドの書式を変更するにはどうすればよいですか?

+0

varcharとテキストの仮説はあまりにも妥当ではなく、これは異常なエラーメッセージです。あなたはSQLブラウザの中でうまく動作すると言いますが、 "関数を実行する"とは言いません。どのような機能ですか? PGバージョンは? –

+0

あなたがそれを日付にしたいのであれば、 'ALTER TABLE" MyTable "ALTER" VisitDate "TYPE date USING" VisitDate ":: date;"や何か変換が必要ですか? – kgrittn

+0

@DanielVérité - この行は、データベース内の他のいくつかのフィールドのフォーマットを変更する関数内にあります。ですから、関数を実行すると、その行にエラーメッセージがスローされます。行を単独で実行すると、エラーメッセージは表示されません。その行なしで関数を実行すると、正しく実行されます。それをさらにテストしたところ、私はその行だけで関数を実行すると正しく動作するので、少し質問を編集する必要があることがわかりました。 – glenatron

答えて

1

私はPG 8.4このやったときとエラーが確認できます。

create table foo(somedate text); 

create function alter_foo() returns void as 
$$ 
alter table foo alter somedate type varchar(10); 
update foo set somedate = to_char(date(somedate),'DD Mon YYYY'); 
$$ 
language sql; 

select alter_foo(); 

を関数呼び出しは、このメッセージで失敗します。

ERROR: table row type and query-specified row type do not match DETAIL: Table has type character varying at ordinal position 1, but query expects text. CONTEXT: SQL function "alter_foo" statement 2

簡単にこの問題を回避するには、代わりにplpgsql言語を選択することですがsql言語の前者は手続き型であり、後者は自動インライン化の候補となる1ライナーやものに適しています。 SQL言語プロセッサは、関数の実行中にデータ型が変更された場合に混乱を招くような形でクエリをあらかじめ解析していると思います。とにかく

あなたはこのようにそれを宣言した場合:

create function alter_foo() returns void as 
$$ 
begin 
    alter table foo alter somedate type varchar(10); 
    update foo set somedate = to_char(date(somedate),'DD Mon YYYY'); 
end; 
$$ language plpgsql; 

意図したとおりに動作しているように見えます。

+0

私はそれが問題かもしれないと思っていましたが、PLPGSQLに関数を変更しようとすると、奇妙に思われる私の 'ALTER'ステートメント(特にフィールド名)の構文エラーで窒息しましたが、Plpgsqlが作成されていないテーブルの変更。私はさらに実験します。 – glenatron

+0

ああ、 "begin/end"ステートメントがありませんでした... – glenatron

関連する問題