Durante el trabajo con PostgreSQL, se han acumulado más de cien funciones para trabajar con directorios del sistema: pg_class, pg_attribute, pg_constraints, etc.
¿Qué hacer con ellos? Se usan relativamente raramente. ¿Incluir en algún proyecto? El cliente de Krasnoyarsk no pagará por tales "tonterías". Y, sin embargo, ¿qué pasa si son útiles para otra persona que no sea el autor? Y decidió ponerlos, como leer libros, en un armario público para quienes lo deseen.
Alguien quiere usarlos en su trabajo. Y alguien interesado en algo más que su experiencia con los catálogos de sistemas.
Pero para no convertir la publicación en una enumeración aburrida, no se sabe por qué se crearon las funciones, decidí detenerme en aquellas que pueden unirse por un objetivo común. Por lo tanto, se seleccionan las funciones que se utilizan para mostrar una lista extendida de características de una tabla de base de datos arbitraria.
La función
admtf_Table_ComplexFeatures devuelve la lista extendida de características de la tabla de la base de datos, que en este artículo se denominará la función head Por lo tanto, el artículo se limitará a considerar las funciones que se llaman en el proceso de ejecución de la función head.
La primera mitad del artículo proporciona comentarios sobre la implementación de funciones. El segundo es el código fuente de las funciones. Para aquellos lectores que solo están interesados en los textos de origen, sugerimos proceder inmediatamente al
Apéndice .
Ver también
Funciones para documentar bases de datos PostgreSQL. Parte dos ;
Funciones para documentar bases de datos PostgreSQL. Tercera parte
Funciones para documentar bases de datos PostgreSQL. El final (parte cuatro) .
¿De qué características avanzadas estamos hablando?
Para tener una idea de lo que se entiende por las características extendidas de la tabla de base de datos, comenzamos considerando la siguiente lista de características. La lista contiene las características de la tabla de la base de datos de Street devuelta por
admtf_Table_ComplexFeatures ( 'public' , 'street' ) .
La siguiente tabla contiene una lista abreviada de las características de la tabla Street. Un conjunto completo de características de esta tabla se proporciona en Materiales complementarios del Apéndice 2.
Tabla 1. Características avanzadas de la tabla Street.

La versión de texto de la tabla en la figura.Categoría | No | Titulo | Comentario | tipo | Tipo base | ? no NULL |
---|
tbl | 0 0 | calle | Lista de calles en asentamientos | | | |
att | 1 | wcrccode | Código de país | wcrccode | letra pequeña | t |
att | 2 | localityid | ID de comunidad | localityid | entero | t |
att | 3 | streetid | ID calle del pueblo | streetid | letra pequeña | t |
att | 4 4 | streettypeacrm | Siglas de la calle | streettypeacrm | personaje (8) | f |
att | 5 5 | nombre de calle | Nombre de la calle | streettypeacrm | varchar (150) | t |
pk | 0 0 | xpkstreet | Clave principal de la mesa de calle | | | |
pkatt | 1 | wcrccode | Código de país | wcrccode | letra pequeña | t |
fk01 | 1 | fk_street_locality | Clave externa de tabla | | | |
fk02 | 2 | fk_street_streettype | Clave externa de tabla | | | |
idx01 | 1 | xie1street | Indice por tipo y nombre de calle del asentamiento | | | |
idx02 | 2 | xie2street | Código postal | | | |
idx03 | 3 | xie3street | Índice de nombres de calles de todos los asentamientos | | | |
idx04 | 4 4 | xpkstreet | El índice único (clave principal) de la tabla de calle | | | |
Enumerando la hostilidad hacia este conjunto de letras y números, puede ver que estamos hablando de las características habituales de una tabla de base de datos:
- Nombres de tablas;
- La lista de atributos de tabla y sus tipos;
- La clave primaria y la lista de claves foráneas de la tabla, junto con los atributos de la tabla que las componen;
- Una lista de índices de tabla.
La unicidad de cada entrada de la lista de características está garantizada por los valores de los campos de "categoría" y el número de serie ("No.") de la característica.
Tabla 2. Categorías de características de la tabla.
La versión de texto de la tabla en la figura.Acrónimo | Cita |
---|
tb | Características de la mesa |
att | Características del atributo de tabla |
seq | Características de secuencia |
pk | Características principales principales |
pkAtt | Características principales del atributo clave |
fk99 | Características clave extranjeras |
fk99att | Características de atributos de clave externa |
fk99rtbl | Características de la tabla referenciada por la clave externa |
fk99ratt | Características del atributo de la tabla a la que hace referencia la clave externa |
Idx99 | Características del índice |
Idx99att | Características de los atributos del índice |
Inhtbl99 | Características de la tabla generada. |
El valor de la categoría es necesario para distinguir diferentes grupos de características entre sí. Un número de serie, para distinguir las características dentro del grupo.
Se pueden declarar varias claves foráneas (CLAVE EXTRANJERA) e índices en la tabla de la base de datos. Por lo tanto, el valor de categoría para estas características y sus descendientes contiene un número de serie. Por ejemplo, una entrada con la clave "Categoría" = idx02att y "No." = 1 indica el primer atributo del segundo índice.
En la lista de categorías anterior, la ubicación del número de serie se indica como '99'.
Observación 1

El código fuente del operador en la figuraSELECT * FROM admtf_Table_ComplexFeatures('pg_catalog','pg_class');
El artículo da ejemplos de las características de las tablas, que se describen brevemente en un esquema auxiliar creado específicamente para demostrar las capacidades de las funciones. Pero el lector, después de haber creado esta o aquella función en su base de datos, puede usar los nombres de sus esquemas y tablas como parámetros. Además, por ejemplo, el directorio pg_class se puede usar como parámetro, aunque en este caso se emite un número limitado de características.
El final del comentario.
Estructura de la función de la cabeza
Fig. 1. Las funciones que causan la función de la cabeza.Tabla 3. Asignación de funciones.
La versión de texto de la tabla en la figura.No | Titulo | Cita |
---|
1 | admtf_Table_Features | La función devuelve una lista de características de la tabla de la base de datos. |
2 | admtf_Table_Attributes | La función devuelve una lista de atributos de tabla de base de datos y sus características. |
3 | admtf_Table_Constraintes | La función devuelve una lista de restricciones de tabla de base de datos y sus características. |
4 4 | admtf_Table_Indexes | La función devuelve una lista de índices de tabla de base de datos y sus características. |
5 5 | admtf_Table_InheritanceChildrens | La función devuelve una lista de tablas generadas por (IHERITS) de la tabla de la base de datos de origen. |
6 6 | admtf_Table_Sequences | La función devuelve una lista de secuencias (SECUENCIA) de la que depende la tabla. |
7 7 | admtf_PrimaryKey_ComplexFeatures | La función devuelve una lista completa (extendida) de características de clave primaria (CLAVE PRIMARIA) de la tabla de la base de datos. |
8 | admtf_ForeignKey_ComplexFeatures | La función devuelve una lista completa (extendida) de características de clave externa (CLAVE EXTRANJERA) de la tabla de la base de datos. |
9 9 | admtf_Index_ComplexFeatures | La función devuelve una lista completa (extendida) de las características del índice de la tabla de la base de datos. |
10 | admtf_Table_ComplexFeatures | La función devuelve una lista completa (extendida) de las características de la tabla de la base de datos. |
Observación 2.
Las descripciones de las funciones se organizarán en el orden que se muestra arriba. La razón es que el artículo tendrá que dividirse en varias partes. Y las funciones dispuestas en este orden se pueden usar independientemente del hecho de que algunas de ellas se describirán solo en las siguientes partes de la publicación.
El final del comentario.
Lista de funciones Admtf_Table_Features de las características de la tabla de base de datos
La función admtf_Table_Features devuelve una lista de características de la tabla de la base de datos. El código fuente se puede ver y descargar aquí.
Como parámetros, la función toma el nombre de la tabla fuente (a_TableName ) y el nombre del esquema dentro del cual se crea la tabla ( a_SchemaName ).
La función extrae los datos principales de la entrada de catálogo pg_class , que contiene, además de las entradas de la tabla, también registros sobre secuencias, vistas, vistas materializadas y tipos compuestos. Por lo tanto, para seleccionar tablas, se usa la condición relkind = 'r' .
SELECT tbl.relname,dsc.description,tbl.relnatts::INTEGER,tbl.relchecks::INTEGER, tbl.relhaspkey,tbl.relhasindex,tbl.relhassubclass,tbl.reltuples::INTEGER FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid LEFT OUTER JOIN pg_description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 WHERE LOWER( nspc.nspname)=LOWER(a_SchemaName) AND tbl.relkind='r' AND LOWER(tbl.relname) =LOWER(a_TableName);
Además, la función accede a los datos del directorio pg_namespace y pg_description . El primero contiene los nombres de los esquemas de la base de datos y el segundo contiene comentarios sobre todos los objetos de la base de datos.
Es importante prestar atención a la condición objsubid = 0 . Define el comentario en la tabla, ya que el valor del campo objoid es el mismo para la tabla y sus atributos. El comentario sobre el atributo de la tabla está contenido en la entrada en la que objsubid coincide con el número de este atributo.
Tabla 4. El resultado de ejecutar la función admtf_Table_Features ('public', 'Street').Titulo | Comentario | Numero de atributos | Número de restricciones CHECK | ? hay una clave primaria | ? son índices declarados | ? hay descendientes | El número de entradas en la tabla. |
---|
calle | Lista de calles en asentamientos | 22 | 0 0 | t | t | f | 20150 |
Observación 3
Presta atención al número de atributos de la tabla de calle. Difiere significativamente del número de atributos especificados en el esquema auxiliar.
Tabla 5. Atributos adicionales de la tabla Street.
attname | atttypid | Attnum | Nota |
---|
cmin | 29 | -4 | Atributo del sistema |
xmin | 28 | -3 | Atributo del sistema |
ctid | 27 | -1 | Atributo del sistema |
wcrccode | 795369 | 1 | Atributo válido |
localityid | 795352 | 2 | Atributo válido |
streetid | 795364 | 3 | Atributo válido |
streettypeacrm | 1919168 | 4 4 | Atributo válido |
nombre de calle | 1043 | 5 5 | Atributo válido |
........ pg.dropped.6 ........ | 0 0 | 6 6 | Atributo remoto |
........ pg.dropped.7 ........ | 0 0 | 7 7 | Atributo remoto |
El hecho es que PostgreSQL, además de los atributos principales, también tiene en cuenta varios atributos del sistema e incluso atributos eliminados.
Comentario final
Función admtf_Table_Attributes lista de atributos de tabla de base de datos y sus características
La función admtf_Table_Attributes devuelve una lista de atributos de la tabla de la base de datos. El código fuente se puede ver y descargar aquí.
Como parámetros, la función toma el nombre de la tabla fuente ( a_TableName ) y el nombre del esquema dentro del cual se crea la tabla ( a_SchemaName ).
La función recupera los datos principales de las entradas de directorio pg_attribute y pg_type . El primero contiene registros con datos sobre los atributos de tablas, vistas, vistas materializadas, tipos compuestos e incluso funciones. El segundo trata sobre las características de los tipos de atributos.
Quizás se requiera alguna aclaración por la forma en que el usuario y los tipos base se definen en la función.
Un atributo de tabla se declara con un tipo personalizado si el campo typbasetype es mayor que 0 en la entrada de directorio pg_type correspondiente, de lo contrario, el atributo es del tipo base. Por lo tanto, el directorio pg_type está involucrado dos veces en la cláusula FROM. En la primera entrada del directorio, se determina la presencia de un tipo de usuario; si no está definido ( typbasetype = 0 ), se genera un valor de tipo base a partir de esta entrada. De lo contrario, el tipo base se determina a partir del registro para el cual btyp.OID = typ.typbasetype.
Directamente, la línea con el tipo base se forma utilizando la función del catálogo del sistema FORMAT_TYPE (type_oid, typemod) . El primer parámetro de los cuales es el tipo base de registros OID. El segundo parámetro es el valor modificador para los tipos que contienen un tamaño. Por ejemplo, VARCHAR (100) o NUMERIC (4,2), DECIMAL (4,2). El valor del parámetro typemod se toma de typ.typtypmod si el atributo es de un tipo de usuario, de lo contrario, de attr.atttypmod , es decir directamente desde un registro de atributos.

El código fuente del operador en la figura SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_class tbl ON tbl.oid = attr.attrelid INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE LOWER( nspc.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname) =LOWER(a_TableName) AND tbl.relkind='r' AND attr.attnum>0 AND attr.atttypID>0 ORDER BY tbl.relname,attr.attnum;
Además, la función accede a los datos del directorio pg_class , pg_namespace y pg_description . Los directorios primero y segundo se usan para buscar atributos por los nombres del esquema y la tabla de la base de datos.
El tercer directorio se utiliza para recuperar el comentario para el atributo de tabla.
El comentario sobre el atributo de la tabla está en la entrada en la que dsc.objoid contiene el OID de la tabla de origen, y dsc.objsubid es el número de serie del atributo en la tabla, es decir. attr.attnum .
Para evitar que la función devuelva el sistema y los atributos remotos, la cláusula WHERE establece la condición attr.attnum> 0 AND attr.atttypID> 0 .
Tabla 6. El resultado de ejecutar la función admtf_Table_Attributes ('public', 'Street').No | Titulo | Tipo personalizado | Tipo base | ? no NULL | Comentario |
---|
1 | wcrccode | wcrccode | letra pequeña | t | Código de país |
2 | localityid | localityid | entero | t | ID de comunidad |
3 | streetid | streetid | letra pequeña | t | ID calle del pueblo |
4 4 | streettypeacrm | streettypeacrm | personaje (8) | f | Siglas de la calle |
5 5 | nombre de calle | | varchar (150) | t | Nombre de la calle del asentamiento. |
Versión de función utilizando alias regclass para tipo oid
Los identificadores de objetos PostgreSQL (OID) son del mismo tipo que OID, que actualmente se implementa como un entero de cuatro bytes sin signo. Pero debido a la presencia de alias de este tipo, un número entero se puede representar como el nombre de un objeto. Y viceversa: convierta el nombre del objeto en un entero de tipo OID.
Como ejemplo, eche un vistazo a la siguiente instrucción SELECT . Inusualmente recupera los nombres de la tabla de atributos y los nombres de sus tipos; en lugar de acceder a los campos de directorio correspondientes con los nombres de estas características, se utilizan:
- attrelid :: regclass (attrelid :: regclass: NAME) ,
- atttypid :: regtype (atttypid :: regtype: NAME)
- typbasetype :: regtype (typbasetype :: regtype: NAME) .
SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype, typ.typbasetype::regtype,attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('public'||'.'||'Street')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
El siguiente es el resultado de ejecutar esta consulta.

En la lista de valores de salida del operador SELECT antes de la conversión utilizando alias del tipo OID, todos los valores, excepto el nombre del atributo, son numéricos, pero como resultado, se muestran los nombres de tabla y los tipos de atributo. Los tipos de valores de salida pueden considerarse en la segunda línea del encabezado de la tabla.
Además, en la cláusula WHERE de la declaración, se encuentra la condición attr.attrelid = ('public' || '.' || 'Street') :: regclass , en el lado izquierdo del cual hay un valor numérico, y a la derecha hay una cadena que se convierte en un valor numérico con usando el alias regclass .

El código fuente del operador en la figura SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE attr.attrelid=( a_SchemaName ||'.'|| a_TableName)::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
Usando el alias regclass de la declaración principal, puede eliminar la conexión a dos directorios. Pero tal mejora casi no tuvo efecto en el rendimiento de la función: en ambas versiones, la función se ejecuta en 11 ms. Quizás debido al hecho de que la tabla de prueba tiene pocos atributos.
Observación 4Un defecto grave en la condición en la forma attr.attrelid = (a_SchemaName || '.' || a_TableName) :: regclass se manifiesta cuando hay un esquema y / o tabla con un nombre inusual en la base de datos. Por ejemplo, "Mi esquema" y / o "Mi tabla" . Dichos valores deben transmitirse entre comillas dobles o utilizar la función QUOTE_IDENT; de lo contrario, la función fallará con un error del sistema.

El código fuente del operador en la figura SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=(' '||'.'||' ')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('" "'||'.'||'" "')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum;
Por lo tanto, prefiero usar condiciones en la forma
INFERIOR (nspc.nspname) = INFERIOR (a_SchemaName) Y INFERIOR (tbl.relname) = INFERIOR (a_TableName) , lo que no conduce a errores del sistema.
Comentario finalAPÉNDICE 1. Scripts
Creación de la función admtf_Table_Features
Los comentarios sobre el código fuente de la función se pueden encontrar aquí.código fuente de la función BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Features (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Features (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (rs_TableName NAME,rs_TableDescription TEXT,rs_NumberOfAttribute INTEGER,rs_NumberOfChecks INTEGER,rs_hasPKey BOOLEAN,rs_hasIndex BOOLEAN,rs_hasSubClass BOOLEAN,rs_NumberOfRow INTEGER) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_TableOID OID; v_TableName NAME; v_TableDescription TEXT; v_TableNumberOfRowCalc INTEGER;
Creación de la función admtf_Table_Attributes
Los comentarios sobre el código fuente de la función se pueden encontrar aquí.código fuente de la función BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER;
Creación de la función admtf_Table_Attributes con el alias Regclass
Los comentarios sobre el código fuente de la función se pueden encontrar aquí.código fuente de la función BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', a_TableName NAME default NULL ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER;
APÉNDICE 2. Materiales adicionales
Esquema de base de datos auxiliar

- PAÍS - Clasificador de países del mundo - OKSM (Clasificación de países del mundo en toda Rusia);
- HOUSEADDR - Lista de números de casas en las calles de los asentamientos;
- LCLTYTYPE - Directorio de tipos de asentamientos;
- LOCALIDAD - Lista de asentamientos;
- STREET — ;
- STREETTYPE — ;
- TERRITORY — (, , , ..);
- TERRITORYTYPE — .
Street ()
.1. Street ().
Categoría | No | Titulo | Comentario | tipo | Tipo base | ? no NULL |
---|
tbl | 0 0 | calle | Lista de calles en asentamientos | | | |
att | 1 | wcrccode | Código de país | wcrccode | letra pequeña | t |
att | 2 | localityid | ID de comunidad | localityid | entero | t |
att | 3 | streetid | ID calle del pueblo | streetid | letra pequeña | t |
att | 4 4 | streettypeacrm | Siglas de la calle | streettypeacrm | personaje (8) | f |
att | 5 5 | nombre de calle | Nombre de la calle | streettypeacrm | varchar (150) | t |
pk | 0 0 | xpkstreet | Clave principal de la mesa de calle | | | |
pkatt | 1 | wcrccode | Código de país | wcrccode | letra pequeña | t |
pkatt | 2 | localityid | ID de comunidad | localityid | entero | t |
pkatt | 3 | streetid | ID calle del pueblo | streetid | letra pequeña | t |
fk01 | 1 | fk_street_locality | Clave externa de tabla | | | |
fk01att | 1 | wcrccode | Código de país | wcrccode | letra pequeña | t |
fk01att | 2 | localityid | ID de comunidad | localityid | entero | t |
fk01rtbl | 0 0 | locality | | | | |
fk01ratt | 1 | wcrccode | | wcrccode | smallint | t |
fk01ratt | 2 | localityid | | localityid | integer | t |
fk02 | 2 | fk_street_streettype | | | | |
fk02att | 1 | streettypeacrm | | streettypeacrm | character(8) | f |
fk02rtbl | 0 0 | streettype | | | | |
fk02ratt | 1 | streettypeacrm | | streettypeacrm | character(8) | t |
idx01 | 1 | xie1street | | | | |
idx01att | 1 | wcrccode | | wcrccode | smallint | t |
idx01att | 2 | localityid | | localityid | integer | t |
idx01att | 3 | streettypeacrm | | streettypeacrm | character(8) | f |
idx01att | 4 4 | streetname | | | varchar(150) | t |
idx02 | 2 | xie2street | | | | |
idx02att | 1 | wcrccode | | wcrccode | smallin | t |
idx02att | 2 | localityid | | localityid | integer | t |
idx02att | 3 | streetname | | | varchar(150) | t |
idx03 | 3 | xie3street | | | | |
idx03att | 1 | streetname | | | varchar(150) | t |
idx04 | 4 4 | xpkstreet | ( ) street | | | |
idx04att | 1 | wcrccode | | wcrccode | smallint | t |
idx04att | 2 | localityid | | localityid | integer | t |
idx04att | 3 | streetid | | streetid | smallint | t |
Ver también
Funciones para documentar bases de datos PostgreSQL. ;Funciones para documentar bases de datos PostgreSQL. Tercera parteFunciones para documentar bases de datos PostgreSQL. El final (parte cuatro) .