web-dev-qa-db-fra.com

Comment obtenir le nom de schéma d'une table de type regclass dans PostgreSQL?

En écrivant une fonction pour tester si une colonne col_name Existe dans une table _tbl, Je voudrais extraire le nom du schéma de la table, qui est passé dans la fonction en tant que regclass paramètre (pour la sécurité ??).

CREATE OR REPLACE FUNCTION column_exists(_tbl regclass, col_name text)
  RETURNS bool AS
$func$
  SELECT EXISTS (
    SELECT 1 FROM information_schema.columns 
    WHERE table_schema=get_schema($1) 
      AND table_name=get_table($1) 
      AND column_name=$2
    );
$func$  LANGUAGE sql;

Donc, si le nom de la table est 'staging.my_table'::regclass, J'aimerais obtenir staging d'une fonction imaginaire get_schema.

Puis-je simplement implémenter cette fonction avec par exemple split_part(_tbl::text, '.', 1)?

De plus, est-il garanti que le nom de la table _tbl, Une fois converti en texte, aura toujours un nom de schéma? (C'est-à-dire en n'omettant pas des choses comme public.))

Je ne connais pas très bien le type regclass. J'ai cherché mais je n'ai pas trouvé comment extraire le nom du schéma, et je voulais juste demander avant de réinventer les roues.

4
tinlyx

Puis-je simplement implémenter cette fonction avec par exemple split_part(_tbl::text, '.', 1)?

Je ne suis pas sûr que ce serait sûr. Au lieu de cela, j'utiliserais,

SELECT nspname
FROM pg_catalog.pg_class AS c
JOIN pg_catalog.pg_namespace AS ns
  ON c.relnamespace = ns.oid
WHERE c.oid = _tbl;

Cela est garanti de fonctionner.

En écrivant une fonction pour tester si une colonne col_name existe dans une table _tbl, Je voudrais extraire le nom du schéma de la table, qui est passé dans la fonction en tant que paramètre regclass (pour la sécurité ??).

Vous pourriez donc faire quelque chose comme,

SELECT nspname
FROM pg_catalog.pg_attribute AS a
JOIN pg_catalog.pg_class AS c
  ON a.attrelid = c.oid
JOIN pg_catalog.pg_namespace AS ns
  ON c.relnamespace = ns.oid
WHERE c.oid = _tbl
  AND a.attname = col_name;

Mise à jour

Si vous avez un identifiant complet, un avec le nom de la table et le nom du schéma à l'intérieur, vous pouvez utiliser parse_ident pour l'analyser en toute sécurité.

6
Evan Carroll

Pour simplifier davantage, vous pouvez utiliser un transtypage en regnamespace - un autre type d'identifiant d'objet introduit avec Postgres 9.5

SELECT relnamespace::regnamespace::text
FROM   pg_catalog.pg_class
WHERE  oid = _tbl;

La conversion d'un type d'identifiant d'objet en text produit une chaîne entièrement qualifiée (uniquement si search_path L'exige) et entre guillemets doubles (uniquement si nécessaire).

Mais vous n'avez pas besoin de tout cela si vous travaillez directement avec pg_attribute :

CREATE OR REPLACE FUNCTION pg_temp.column_exists(_tbl regclass, _col_name text)
   RETURNS bool AS
$func$
SELECT EXISTS (
   SELECT FROM pg_catalog.pg_attribute
   WHERE attrelid = _tbl
   AND   attname = _col_name
   );
$func$  LANGUAGE sql;

Plus simple, plus court, plus rapide.

3
Erwin Brandstetter