CREAR TABLA COMO vs SELECCIONAR EN

16

PostgreSQL es compatible CREATE TABLE ASy ¿ SELECT INTOcuándo uso ambos?

CREATE TABLE AS - definir una nueva tabla a partir de los resultados de una consulta

CREATE TABLE AScrea una tabla y la llena con datos calculados por un SELECTcomando. Las columnas de la tabla tienen los nombres y tipos de datos asociados con las columnas de salida delSELECT (excepto que puede anular los nombres de columna dando una lista explícita de nuevos nombres de columna).

CREATE TABLE AStiene cierta semejanza con la creación de una vista, pero en realidad es bastante diferente: crea una nueva tabla y evalúa la consulta solo una vez para llenar la nueva tabla inicialmente. La nueva tabla no realizará un seguimiento de los cambios posteriores en las tablas de origen de la consulta. Por el contrario, una vista reevalúa su SELECTdeclaración de definición cada vez que se consulta.

Y entonces.

SELECT INTO - definir una nueva tabla a partir de los resultados de una consulta

SELECT INTOcrea una nueva tabla y la llena con datos calculados por una consulta. Los datos no se devuelven al cliente, como ocurre con una normal SELECT. Las columnas de la nueva tabla tienen los nombres y los tipos de datos asociados con las columnas de salida de SELECT.

Evan Carroll
fuente

Respuestas:

15

Sin la explicación, use siempre CREATE TABLE ASsin excepción. En la parte inferior de cada uno debajo de NOTAS esto se aclara,

Notas para SELECT INTO,

CREATE TABLE ASes funcionalmente similar a SELECT INTO. CREATE TABLE ASes la sintaxis recomendada, ya que esta forma de SELECT INTOno está disponible en ECPG o PL / pgSQL, porque interpretan la cláusula INTO de manera diferente. Además, CREATE TABLE ASofrece un superconjunto de la funcionalidad proporcionada por SELECT INTO.

Notas para CREATE TABLE AS,

Este comando es funcionalmente similar a SELECT INTO, pero se prefiere ya que es menos probable que se confunda con otros usos de la SELECT INTOsintaxis. Además, CREATE TABLE ASofrece un superconjunto de la funcionalidad que ofrece SELECT INTO.

También en la sección de Compatibilidad de los documentos SELECT INTOva más allá,

El estándar SQL se utiliza SELECT INTOpara representar valores de selección en variables escalares de un programa host, en lugar de crear una nueva tabla. De hecho, este es el uso que se encuentra en ECPG (consulte el Capítulo 34) y PL / pgSQL (consulte el Capítulo 41). El uso de PostgreSQL SELECT INTOpara representar la creación de tablas es histórico. Es mejor usar CREATE TABLE ASpara este propósito en un nuevo código.

Entonces tenemos,

  1. PostgreSQL cree que es confuso porque SELECT INTOotras cosas en contextos solo están disponibles en PL / pgSQL y ECPG.
  2. CREATE TABLEadmite más funciones (supongo que se refieren a WITH OIDS, y TABLESPACE, IF NOT EXISTS).
  3. SELECT INTO para la creación de la tabla está "en desuso".

Como nota al margen, la sintaxis de un CTAS con un CTE puede parecer un poco extraña. , y también SELECT INTO puede ser algún tipo de retención sobre QUELRETRIEVE INTO . QUEL fue el predecesor de SQL, que utilizó el predecesor de PostgreSQL (INGRES).

Evan Carroll
fuente
1

Hay otra cosa que noté que falta en la respuesta aceptada. El uso CREATE TABLE ASconserva el atributo anulable de cada columna que parece ser ignorado por SELECT INTO.

Solo sobre esta base, lo recomendaría CREATE TABLE AS. Un caso de uso común para ambas declaraciones es cargar datos de una consulta de larga ejecución en una tabla sin bloquear esa tabla durante la duración de su consulta. Cree una tabla temporal utilizando uno de los comandos anteriores, coloque los resultados de la consulta de larga duración allí y luego inserte esos resultados en la tabla original. Preservar el atributo anulable en su tabla temporal reduce las posibilidades de que falle su segunda inserción.

Probé esto en PG 11, por lo que quizás sea una característica más nueva ya que esta pregunta fue respondida.

shrumm
fuente
Una consulta de larga duración no bloquea ninguna tabla. Entonces, la motivación para usar CTAS por esa razón es inútil
a_horse_with_no_name