2017-10-02 1 views
2

Ich habe versucht, eine Erklärung zu schreiben, wenn ein Tabellenzeilen enthält zu überprüfen:Wie überprüft man, ob eine Tabelle Zeilen enthält, wenn der Tabellenname als Parameter übergeben wird?

SELECT COUNT(*) FROM $1 ; 

Wenn ich dachte, in den Tabellennamen in passieren würde: $ 1

bekomme ich folgende Fehlermeldung:

Syntaxfehler bei oder in der Nähe von "$ 1"

Was mit meiner Aussage falsch ist?

+0

Welche verwendeten DBMS? Es erfordert Dynamic sql –

+0

Ich benutze Postgres –

+0

Überprüfen Sie diese Frage https://StackOverflow.com/Questions/20772195/how-to-select-from-variable-that-is-a-table-name-n-postgre-9 -2 und https://stackoverflow.com/questions/10705616/table-name-as-a-postgresql-function-parameter –

Antwort

0

Sie können diese Informationen aus dem Systemkatalog viel billiger und schneller als die Abfrage der Tabelle selbst erhalten.

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' ist nur ein ** Schätzwert ** es könnte nicht genau sein. –

+0

Richtig, aber jede Zahl größer als 0 beweist Existenz. Das OP hat nicht gefragt, wie viele Zeilen in der Tabelle sind, und die Schätzung wird mindestens eine Seite im Wert von Zeilen zurückgeben. –

+0

dämmerte mir was @a_horse_with_no_name gemeint ... für sehr kleine Tabellen modifiziert. –

0

Die base driver tut nur die grundlegende Abfrage Formatierung, die auf der Serverebene unterstützt wird, die nicht dynamische Tabellennamen nicht unterstützt.

Dies bedeutet, dass der Tabellenname auf Ihrer Seite maskiert werden muss. Sie können entweder manuell, oder Sie können auf eine Bibliothek verlassen, die es unterstützt, wie das folgende Beispiel, dass verwendet 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 
    }); 

Oder durch Named Parameters mit:

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  
    }); 

Filter :name das erzählt Formatierungsmodul, um es als SQL-Name zu entkommen. Dieser Filter hat auch eine kürzere Version ~, wenn Sie bevorzugen, d. H. $1~ oder ${table~} entsprechend.

Außerdem verwenden wir die Methode one, da diese Abfrage immer ein Einzeilenergebnis zurück erwartet.

0

Sie können es nicht mit vorbereiteten Anweisung tun. Verwenden Sie die Funktion, wie Kirk es vorschlägt. Der einzige Unterschied, vielleicht sind Sie sicherer ersten Reihe zu wählen, wie:

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 direkt, die Sie passieren zu execute vorbereitete Anweisung Werte können nicht Bezeichner sein, doch überall werden sie in einer Art und Weise erwähnt, dass Kennung konnte nicht sein, zum Beispiel:

A generic Plan geht davon aus, dass jeder Wert ist die die Spalten unterschiedlicher Werte EXECUTE geliefert und dieser Spalt Werte sind gleichmäßig verteilt .

($ 1 ist ein Spaltenwert mit oder ohne einige Eigenschaften.)

Verwandte Themen