2017-10-02 9 views
2

の:$ 1テーブル名をパラメータとして渡すときにテーブルに行が含まれているかどうかを確認するにはどうすればいいですか?私はテーブルの行が含まれているかどうかをチェックするために文を書くためにしようとしていた

私は、次のエラーメッセージが出ます::

SELECT COUNT(*) FROM $1 ; 

考え出し私はに、テーブル名を渡したい場合

が私の文の何が問題である "$ 1" で、または近く

構文エラー?

+0

?これは動的SQLが必要です –

+0

私はpostgresを使用しています –

+0

この問題を確認するhttps://stackoverflow.com/questions/20772195/how-to-select-from-variable-that-is-a-table-name-n-postgre-9 -2とhttps://stackoverflow.com/questions/10705616/table-name-as-a-postgresql-function-parameter –

答えて

0

この情報は、システムカタログから、テーブル自体を照会するよりもずっと安価で高速に取得できます。

CREATE OR REPLACE FUNCTION table_empty(tablename text, tableschema text) 
RETURNS BOOLEAN AS $$ 
BEGIN 
RETURN (SELECT CASE WHEN (reltuples::integer > 0) 
    THEN false 
    ELSE (SELECT count(*) = 0 
     FROM quote_ident(tableschema || '.' || tablename) ) 
    END 
     FROM pg_namespace nc 
     JOIN pg_class c 
     ON nc.oid = c.relnamespace 
     WHERE relname=tablename AND nc.nspname = tableschema); 

END; 
$$ 
LANGUAGE plpgsql; 

SELECT table_empty('pg_class','pg_catalog'); 
table_empty 
----------- 
f 

1 row 
+0

'reltuples'は推定値**です**正確ではないかもしれません。 –

+0

真であるが、0より大きい任意の数が存在することを証明する。 OPはテーブルにいくつの行があるか尋ねなかったので、推定値は少なくとも1ページ分の行を返します。 –

+0

私に何が起きたか@a_horse_with_no_nameの意味...非常に小さなテーブルのために修正されました。 –

0

base driver動的テーブル名をサポートしていないサーバーレベルでサポートの唯一の基本的なクエリの書式設定を行います。

これは、あなたの側でテーブル名をエスケープする必要があることを意味します。その下の例では、pg-promiseを使用していますように、あなたは手動でこれを行うことができ、またはあなたはそれをサポートしているライブラリに頼ることができます。

db.one('SELECT count(*) FROM $1:name', table, a => +a.count) 
    .then(count => { 
     // count = the integer record count 
    }) 
    .catch(error => { 
     // either table doesn't exist, or a connectivity issue 
    }); 

または、Named Parametersを使用して:

db.one('SELECT count(*) FROM ${table:name}', {table}, a => +a.count) 
    .then(count => { 
     // count = the integer record count 
    }) 
    .catch(error => { 
     // either table doesn't exist, or a connectivity issue  
    }); 

フィルター:nameを伝えます書式設定エンジンをSQL名としてエスケープします。また、このフィルタのバージョンは~、希望する場合は$1~または${table~}となります。

また、oneというメソッドを使用しています。そのクエリでは常に1行の結果が返されるためです。

0

準備文ではできません。 Kirkが示唆しているように関数を使用する。あなたは、識別子することはできませんexecuteプリペアドステートメントに渡す、まだどこでも彼らはその識別子が邪魔にできなかったmentionnedされている値を直接

t=# create or replace function tempty(tn text) returns boolean as 
$$ 
declare 
c int; 
begin 
    execute format('select 1 from %I limit 1',tn) into c; 
    return NOT coalesce(c,0) > 0; 
end; 
$$ language plpgsql 
; 
CREATE FUNCTION 
t=# create table empty(i int); 
CREATE TABLE 
t=# select tempty('empty'); 
tempty 
-------- 
t 
(1 row) 

t=# select tempty('pg_class'); 
tempty 
-------- 
f 
(1 row) 

docs do not say:唯一の違いは、多分あなたは次のように、最初の行を選択する方が安全です例えば、である。

一般的な計画の実行に供給される各値は 列の個別値の一つであり、その列の値が均一 分布していることを前提としています。使用しているDBMS

($ 1はいくつかのプロパティの有無にかかわらず列値である。)

関連する問題