Crear una tabla "INTO" con clave primaria

8

Quizás para esta comunidad mi problema es fácil, pero para mí (un simple programador de Java) es un GRAN problema.

Tengo un Big DB con más y más datos. Entonces, el administrador externo de db había creado un trabajo que me mostraba en una tabla temporal los datos que necesitaba. Pero él había creado la tabla sin una clave primaria y cuando con mi proyecto Java voy a leer esta tabla, obtengo un error.

No puedo leer esta tabla porque la clave primaria no existe.

¿Puedo insertar en el procedimiento la posibilidad de crear una clave primaria autoincremental sin cambiar la estructura de este procedimiento complejo?

Este es el comienzo del código de procedimiento almacenado:

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER Procedure [dbo].[spSchedula_Scadenzario]
as
begin

    drop table MYDB.dbo.tmpTable


 select 
  aa.*
    into MYDB.dbo.tmpTable 
from (...)

Gracias por adelantado

PaolaG
fuente

Respuestas:

5

Parece que está buscando la función IDENTITY () :

Solo se usa en una instrucción SELECT con una cláusula INTO table para insertar una columna de identidad en una nueva tabla.

USE [MYDB]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER Procedure [dbo].[spSchedula_Scadenzario]
as
begin

    drop table MYDB.dbo.tmpTable


     select 
    -- Create new identity here.
    NewPrimaryKey = IDENTITY(int, 1, 1),
    aa.*
    into MYDB.dbo.tmpTable 
from (...)
Shaneis
fuente
14
@Paola Aunque para ser claros, esto solo aborda la parte de incremento automático de la pregunta. La tabla todavía no tiene clave primaria.
Martin Smith
9

Algunas alternativas para agregar la columna de incremento automático mediante la IDENTITY()función sugerida por @Shaneis son:

  1. Cree la tabla explícitamente usando en CREATE TABLElugar de usar SELECT INTO. Prefiero este método, ya que le brinda un control completo sobre la Tabla que se está creando, como incluir la columna de incremento automático y especificar que sea la Clave primaria. Por ejemplo:

    CREATE TABLE dbo.tmpTable
    (
      tmpTableID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
      ...
      {all columns represented by aa.* in the sample query in the Question}
    );
  2. Si no puede cambiar cómo / cuándo / dónde se está creando la tabla, siempre puede agregar una Columna más tarde, y al hacerlo, puede especificar que sea una IDENTITYcolumna y que se cree la Clave primaria. Por ejemplo:

    ALTER TABLE [dbo].[tmpTable]
      ADD [tmpTableID] INT NOT NULL
      IDENTITY(1, 1)
      PRIMARY KEY;

    Esto incluso funciona si la tabla ya tiene datos: la nueva IDENTITYcolumna se completará como se esperaba, comenzando con el valor especificado para el seedparámetro. Sin embargo, no hay forma de controlar el orden en que se asignan los valores (que es una de varias razones para ir con la opción # 1, si es posible).

Notas adicionales:

  • ¿Está seguro de que necesita una Clave primaria y no simplemente una columna de incremento automático / única? Si bien suele ser una buena idea tener una Clave primaria, no es necesaria ni es lo mismo que una columna de incremento automático. Solo pregunto porque tanto el título como el texto de esta Pregunta indican que necesita una Clave principal, pero en un comentario sobre la Respuesta dice que aceptó que simplemente funcionó la columna de incremento automático.

  • La tabla que está utilizando no es realmente una tabla temporal. Las tablas temporales reales tienen nombres que comienzan con #o ##para tablas temporales globales. La tabla que está utilizando dbo.tmpTablees solo una tabla regular y permanente con el prefijo "tmp" para indicar que probablemente sea solo para este proceso y no sea parte del modelo de datos.

    Si el código de la aplicación no necesita acceder a esta Tabla "temporal", y la única referencia a ella está dentro de este Procedimiento almacenado, entonces puede considerar cambiarlo para que sea una Tabla temporal real, que tiene la ventaja de ser limpiado cuando el proceso se completa, en cuyo caso no necesitaría la DROP TABLEdeclaración.

  • Si va a utilizar una tabla permanente en lugar de una tabla temporal (en cuyo caso debe limpiarla usted mismo), la DROP TABLEdeclaración debe ser condicional, de modo que no se produzca un error si la tabla no existe:

    IF (OBJECT_ID(N'dbo.tmpTable') IS NOT NULL)
    BEGIN
       DROP TABLE dbo.tmpTable;
    END;
  • En lugar de hacerlo SELECT *, debe especificar la lista de columnas completa. El uso *hace que sea más probable que el proceso se interrumpa cuando agrega columnas / campos a tablas o subconsultas (lo que aasea ​​un alias).

Solomon Rutzky
fuente