Creare una tabella "INTO" con chiave primaria


8

Forse per questa comunità il mio problema è semplice, ma per me (un semplice programmatore Java) è un GRANDE problema.

Ho un Big DB con sempre più dati. Quindi, l'amministratore di database esterno aveva creato un lavoro che mi mostrava in una tabella temporanea i dati di cui avevo bisogno. Ma aveva creato la tabella senza una chiave primaria e quando con il mio progetto Java andavo a leggere questa tabella, ottengo un errore.

Non riesco a leggere questa tabella perché la chiave primaria non esiste.

Posso inserire nella procedura la possibilità di creare una chiave primaria autoincrementale senza modificare la struttura di questa complessa procedura?

Questo è l'inizio del codice della procedura memorizzata:

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 (...)

Grazie in anticipo

Risposte:


5

Sembra che tu stia cercando la funzione IDENTITY () :

Viene utilizzato solo in un'istruzione SELECT con una clausola di tabella INTO per inserire una colonna di identità in una nuova tabella.

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 (...)

14
@Paola Anche se per essere chiari, questo risolve solo la parte di incremento automatico della domanda. La tabella non ha ancora una chiave primaria.
Martin Smith,

9

Alcune alternative all'aggiunta della colonna di auto-incremento tramite la IDENTITY()funzione come suggerito da @Shaneis sono:

  1. Crea la tabella esplicitamente usando CREATE TABLEinvece di usare SELECT INTO. Preferisco di gran lunga questo metodo in quanto ti dà il controllo completo sulla tabella che viene creata, ad esempio includendo la colonna di auto-incremento e specificando che è la chiave primaria. Per esempio:

    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. Se non puoi cambiare come / quando / dove viene creata la tabella, puoi sempre aggiungere una colonna in un secondo momento e, in tal caso, puoi specificare che sia una IDENTITYcolonna e su cui deve essere creata la chiave primaria. Per esempio:

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

    Funziona anche se la tabella contiene già dei dati: la nuova IDENTITYcolonna verrà popolata come previsto, a partire dal valore specificato per il seedparametro. Tuttavia, non esiste alcun modo per controllare l'ordine in cui sono assegnati i valori (che è uno dei diversi motivi per scegliere l'opzione 1, se possibile).

Note aggiuntive:

  • Sei sicuro di aver bisogno di una chiave primaria e non semplicemente di una colonna con incremento automatico / unica? Sebbene in genere sia una buona idea avere una chiave primaria, non è richiesta né uguale a una colonna con incremento automatico. Chiedo solo perché sia ​​il titolo che il testo di questa domanda affermano che è necessaria una chiave primaria, ma in un commento sulla risposta si afferma che si è accettato il fatto che la colonna di incremento automatico funzionava semplicemente.

  • La tabella che stai utilizzando non è in realtà una tabella temporanea. Le tabelle temporanee reali hanno nomi che iniziano con #, o ##per le tabelle temporanee globali. La tabella che stai utilizzando dbo.tmpTableè solo una tabella normale e permanente con il prefisso "tmp" per indicare che probabilmente è solo per questo processo e non fa parte del modello di dati.

    Se il codice dell'app non ha bisogno di accedere a questa tabella "temporanea" e l'unico riferimento ad essa è all'interno di questa Stored procedure, allora potresti considerare di cambiarla come una vera tabella temporanea, che ha il vantaggio di essere ripulita quando il processo viene completato, nel qual caso non è necessaria la DROP TABLEdichiarazione.

  • Se si utilizzerà una tabella permanente anziché una tabella temporanea (nel qual caso è necessario pulirla da soli), l' DROP TABLEistruzione dovrebbe essere condizionale, in modo che non si verifichi se la tabella non esiste:

    IF (OBJECT_ID(N'dbo.tmpTable') IS NOT NULL)
    BEGIN
       DROP TABLE dbo.tmpTable;
    END;
    
  • Invece di fare SELECT *, è necessario specificare l'elenco di colonne completo. L'uso *rende più probabile l'interruzione del processo quando si aggiungono colonne / campi a tabelle o sottoquery (qualunque aasia un alias per).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.