infowindow
フィールドが存在するかどうかを特定のテーブルでチェックする関数を作成する必要があります。存在する場合、関数はselect * from table
を返す必要がありますが、存在しない場合は、追加のid
フィールドを返す必要があります。
CREATE OR REPLACE FUNCTION getxo_ocx_cincu_preparar_infowindow(
guretabla character varying)
RETURNS TABLE AS
$BODY$
DECLARE
tabla ALIAS FOR $1;
BEGIN
IF EXISTS (SELECT 1
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE n.nspname = current_schema() -- default to current schema
AND c.relname = tabla
AND a.attname = 'infowindow'
AND NOT a.attisdropped)
THEN
RETURN QUERY EXECUTE 'SELECT * from ' ||tabla ;
ELSE
RETURN QUERY EXECUTE 'SELECT *, ID:' || id::text ||' as infowindow
from ' ||tabla ;
END IF;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
RETURNS SETOF RECORDS
を使用する場合、関数を選択するときに、列を指定する必要がありますが、これはわかりません。また、RETURNS TABLE
を使用する場合は、フィールドも指定する必要があるため、その方法がわかりません。
SQLは戻り値の型を知る必要があるため、これを解決するのは困難です呼び出し時。
また、plpgsql関数には明確に定義された戻り値の型が必要です。
匿名レコードを返すことを選択した場合、定義したもの、つまり匿名レコードを取得します。 Postgresは何が入っているのかわかりません。したがって、タイプを分解するには、列定義リストは必須です。
正確な要件に応じて、さまざまな回避策があります。戻り値の型を知る方法がある場合呼び出し時、この回答の最後の章で概説されているようにポリモーフィック型をお勧めします(「さまざまな完全なテーブル型」):
PL/pgSQL関数をリファクタリングして、さまざまなSELECTクエリの出力を返します
しかし、それは戻り値の型に別の列を追加することをカバーしていません関数内の実行時。それは不可能です。私はアプローチ全体を再考します。
あなたの現在のアプローチに関して、私が考えることができる最も近いものは、シングル内の2回目の呼び出しでクエリする一時テーブル( またはカーソル )です。トランザクション。
コードにその他の問題がいくつかあります。以下の注を参照してください。
_CREATE OR REPLACE FUNCTION f_tbl_plus_infowindow (_tbl regclass) -- regclass!
RETURNS void AS -- no direct return type
$func$
DECLARE
-- appending _tmp for temp table
_tmp text := quote_ident(_tbl::text || '_tmp');
BEGIN
-- Create temp table only for duration of transaction
EXECUTE format(
'CREATE TEMP TABLE %s ON COMMIT DROP AS TABLE %s LIMIT 0', _tmp, _tbl);
IF EXISTS (
SELECT 1
FROM pg_attribute a
WHERE a.attrelid = _tbl
AND a.attname = 'infowindow'
AND a.attisdropped = FALSE)
THEN
EXECUTE format('INSERT INTO %s SELECT * FROM %s', _tmp, _tbl);
ELSE
-- This is assuming a NOT NULL column named "id"!
EXECUTE format($x$
ALTER TABLE %1$s ADD COLUMN infowindow text;
INSERT INTO %1$s
SELECT *, 'ID: ' || id::text
FROM %2$s $x$
,_tmp, _tbl);
END IF;
END
$func$ LANGUAGE plpgsql;
_
呼び出しは単一のトランザクションで行う必要があります。クライアントによっては、明示的なトランザクションを開始する必要がある場合があります。
_BEGIN;
SELECT f_tbl_plus_infowindow ('tbl');
SELECT * FROM tbl_tmp; -- do something with the returned rows
ROLLBACK; -- or COMMIT, does not matter here
_
または、セッションの間、一時テーブルを存続させることもできます。ただし、繰り返し呼び出される名前の衝突には注意してください。
古いALIAS
コマンド の代わりにパラメーター名を使用してください。
現在のスキーマを実際に「デフォルト」にするには、表示するより単純なクエリを使用します。 regclass
を使用すると、トリックが自動的に実行されます。詳細:
さらに、これにより、元のコードの非標準(または悪意を持って不正な形式)のテーブル名からの構文エラーやSQLインジェクションの可能性も回避されます。
ELSE
句のコードはまったく機能しません。
_TABLE tbl;
_は基本的に_SELECT * FROM tbl;
_の略です。