Mysql
 sql >> Database >  >> RDS >> Mysql

SQL:creazione di una tabella di relazioni con 2 diversi auto_increment

Concetti

Hai frainteso alcuni concetti di base e le difficoltà ne derivano. Dobbiamo prima affrontare i concetti, non il problema come lo percepisci e, di conseguenza, il tuo problema scomparirà.

ID a incremento automatico, che ovviamente sono chiavi primarie.

No non lo sono. Questo è un malinteso comune. E i problemi sono garantiti.

Un ID campo non può essere una chiave primaria in senso inglese o tecnico o relazionale.

  • Certo, in SQL puoi dichiarare qualsiasi deve essere un PRIMARY KEY , ma questo non la trasforma magicamente in una Chiave Primaria nel senso inglese, tecnico o relazionale. Puoi chiamare un chihuahua "Rottweiller", ma questo non lo trasforma in un Rottweiller, rimane un chihuahua. Come ogni linguaggio, SQL esegue semplicemente i comandi che gli dai, non comprende PRIMARY KEY per significare qualcosa di relazionale, colpisce semplicemente un indice univoco sulla colonna (o campo).

  • Il problema è che hai dichiarato il ID essere una PRIMARY KEY , tu pensi come chiave primaria e potresti aspettarti che ha alcune delle qualità di una Chiave Primaria. Fatta eccezione per l'univocità dell'ID valore , non fornisce alcun vantaggio. Non ha nessuna delle qualità di una Chiave Primaria, o qualsiasi tipo di Chiave Relazionale per quella materia. Non è una chiave nel senso inglese, tecnico o relazionale. Dichiarando una chiave non chiave, ti confonderai solo e scoprirai che c'è qualcosa di terribilmente sbagliato solo quando l'utente si lamenta dei duplicati nella tabella.

Le tabelle relazionali devono avere riga unicità

Una PRIMARY KEY su un ID il campo non fornisce riga unicità. Pertanto non è una tabella relazionale contenente righe e, in caso contrario, è un file contenente record. Non ha alcuna integrità o potenza (in questa fase sarai a conoscenza solo della potenza di unione) o velocità di una tabella in un database relazionale.

Esegui questo codice (MS SQL 2008) e dimostralo a te stesso. Per favore, non leggere semplicemente questo e capirlo, quindi procedi a leggere il resto di questa risposta, questo codice deve essere eseguito prima di leggere ulteriormente . Ha valore curativo.

    CREATE TABLE dumb_file (
        id         INT      NOT NULL  IDENTITY  PRIMARY KEY,
        name_first CHAR(30) NOT NULL,
        name_last  CHAR(30) NOT NULL
        )

    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds
    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds, but not intended
    INSERT dumb_file VALUES ( "Mickey", "Mouse" )  -- succeeds, but not intended

    SELECT * FROM dumb_file

Nota che hai righe duplicate . Le tabelle relazionali devono avere righe univoche . Un'ulteriore prova che non hai una tabella relazionale, o nessuna delle sue qualità.

Nota che nel tuo rapporto l'unica cosa che è univoca è l'ID campo, di cui nessun utente si preoccupa, nessun utente vede, perché non sono dati, è un'ulteriore sciocchezza che qualche "insegnante" molto stupido ti ha detto di inserire in ogni file. Hai record unicità ma non riga unicità.

In termini di dati (i dati reali meno le aggiunte estranee), i dati name_last e name_first può esistere senza il ID campo. Una persona ha un nome e un cognome senza un documento d'identità stampigliato sulla fronte.

La seconda cosa che stai usando che ti confonde è AUTOINCREMENT. Se stai implementando un sistema di archiviazione di record senza capacità relazionali, sicuramente è utile, non devi codificare l'incremento durante l'inserimento dei record. Ma se stai implementando un database relazionale, non serve a nulla, perché non lo utilizzerai mai. Ci sono molte funzionalità in SQL che la maggior parte delle persone non usa mai.

Azione correttiva

Quindi, come si aggiorna, eleva, quel file dumb che è pieno di righe duplicate in una tabella relazionale, al fine di ottenere alcune delle qualità e dei vantaggi di una tabella relazionale? Ci sono tre passaggi per farlo.

  1. Devi capire le chiavi

    • E da quando siamo passati dai file ISAM degli anni '70 al Modello Relazionale , devi comprendere le Chiavi relazionali . Ovvero se desideri ottenere i benefici (integrità, potenza, velocità) di un Database Relazionale.

    Dr EF Cood, nel suo RM , ha dichiarato che:

    una chiave è composta dai dati

    e

    le righe di una tabella devono essere univoche

    La tua "chiave" non è composta dai dati. È un parassita aggiuntivo, non dati, causato dal fatto che sei stato infettato dalla malattia del tuo "insegnante". Riconoscilo come tale, e concediti la piena capacità mentale che Dio ti ha dato (nota che non ti chiedo di pensare in termini isolati o frammentati o astratti, tutti gli elementi di un database devono essere integrati tra loro). Crea una vera chiave dai dati e solo dai dati. In questo caso, c'è solo una chiave possibile:(name_last, name_first).

  2. Prova questo codice , dichiara un vincolo univoco sui dati:

         CREATE TABLE dumb_table (
            id         INT      NOT NULL  IDENTITY  PRIMARY KEY,
            name_first CHAR(30) NOT NULL,
            name_last  CHAR(30) NOT NULL
    
            CONSTRAINT UK 
                UNIQUE ( name_last, name_first )
            )
    
        INSERT dumb_table VALUES ( "Mickey", "Mouse" )  -- succeeds
        INSERT dumb_table VALUES ( "Mickey", "Mouse" )  -- fails, as intended
        INSERT dumb_table VALUES ( "Minnie", "Mouse" )  -- succeeds
    
        SELECT * FROM dumb_table
    

    Ora abbiamo unicità di riga . Questa è la sequenza che succede alla maggior parte delle persone:creano un file che consente i duplicati; non hanno idea del motivo per cui i duplicati appaiono nei menu a discesa; l'utente urla; modificano il file e aggiungono un indice per evitare duplicati; vanno alla prossima correzione del bug. (Potrebbero farlo correttamente o meno, questa è un'altra storia.)

  3. Il secondo livello. Per le persone pensanti che pensano oltre le correzioni. Dato che ora abbiamo l'unicità della riga, quello che in nome del Cielo è lo scopo del ID campo, perché ce l'abbiamo anche noi??? Oh, perché il chihuahua si chiama Rotty e abbiamo paura di toccarlo.

    La dichiarazione che si tratta di una PRIMARY KEY è falso, ma rimane, provocando confusione e false aspettative. L'unica chiave autentica che c'è è il (name_last, name_fist), ed è una Chiave alternativa a questo punto.

    Pertanto il ID il campo è del tutto superfluo; e così è l'indice che lo supporta; e così è lo stupido AUTOINCREMENT; e così è la falsa dichiarazione che si tratta di una PRIMARY KEY; e tutte le aspettative che potresti avere su di esso sono false.

    Rimuovere quindi il superfluo ID campo. Prova questo codice :

        CREATE TABLE honest_table (
            name_first CHAR(30) NOT NULL,
            name_last  CHAR(30) NOT NULL
    
            CONSTRAINT PK 
            PRIMARY KEY ( name_last, name_first )
            )
    
        INSERT honest_table VALUES ( "Mickey", "Mouse" )  -- succeeds
        INSERT honest_table VALUES ( "Mickey", "Mouse" )  -- fails, as intended
        INSERT honest_table VALUES ( "Minnie", "Mouse" )  -- succeeds
    
        SELECT * FROM honest_table
    

    Funziona bene, funziona come previsto, senza campi e indici estranei.

    Per favore, ricordalo e fallo bene, ogni singola volta.

Falsi insegnanti

In questi ultimi tempi, come consigliato, ne avremo molti. Nota bene, gli "insegnanti" che propagano ID colonne, in virtù dell'evidenza dettagliata in questo post, semplicemente non comprendono il Modello relazionale o Database relazionali. Soprattutto quelli che ne scrivono libri.

Come evidenziato, sono bloccati nella tecnologia ISAM precedente al 1970. Questo è tutto ciò che capiscono, ed è tutto ciò che possono insegnare. Usano un contenitore di database SQL, per facilitare l'accesso, il ripristino, il backup, ecc., ma il contenuto è puro sistema di archiviazione dei record senza integrità relazionale, potenza o velocità. AFAIC, è una grave frode.

Oltre a ID campi, ovviamente, ci sono diversi elementi che sono concetti chiave Relazionale o no, che presi insieme, mi portano a trarre una conclusione così grave. Questi altri elementi esulano dallo scopo di questo post.

Una coppia in particolare di idioti sta attualmente organizzando un assalto alla Prima Forma Normale. Appartengono al manicomio.

Risposta

Ora per il resto della tua domanda.

C'è un modo per creare una tabella relazionale senza perdere le funzioni di incremento automatico?

Questa è una frase contraddittoria. Confido che capirai dalla mia spiegazione, le tabelle relazionali non ne hanno bisogno per AUTOINCREMENT "caratteristiche"; se il file ha AUTOINCREMENT , non è una tabella relazionale.

AUTOINCREMENT va bene solo per una cosa:se, e solo se, vuoi creare un foglio di calcolo Excel nel contenitore del database SQL, riempilo con i campi chiamati A, B, e C, in alto e registra i numeri in basso a sinistra. In termini di database, questo è il risultato di un SELECT, una vista appiattita dei dati, cioè non la fonte di dati, che è organizzato (normalizzato).

Un'altra soluzione possibile (ma non preferita) potrebbe essere la presenza di un'altra chiave primaria nella prima tabella, che è il nome utente dell'utente, ovviamente non con un'istruzione di incremento automatico. È inevitabile?

Nel lavoro tecnico non ci interessano le preferenze, perché sono soggettive e cambiano continuamente. Abbiamo a cuore la correttezza tecnica, perché è oggettiva e non cambia.

Sì, è inevitabile. Perché è solo questione di tempo; numero di bug; numero di "non posso fare"; numero di utenti urla, finché non affronti i fatti, superi le tue false dichiarazioni e ti rendi conto che:

  • l'unico modo per garantire che l'utente riga sono univoci, che i nomi_utente sono univoci, significa dichiarare un UNIQUE vincolo su di esso

  • e sbarazzati di user_id o id nel file utente

  • che promuove user_name a PRIMARY KEY

Sì, perché tutto il tuo problema con il terzo tavolo, non a caso, viene poi eliminato.

Quel terzo tavolo è un Tavolo associativo . L'unica chiave richiesta (Chiave primaria) è un composto delle due chiavi primarie principali. Ciò garantisce l'unicità delle righe , che sono identificati dalle loro chiavi, non dai loro IDs.

Te ne sto avvisando perché gli stessi "insegnanti" che ti hanno insegnato l'errore di implementare ID campi, insegna l'errore di implementazione di ID campi della tabella associativa, dove, proprio come con una tabella ordinaria, è superflua, non serve a nulla, introduce duplicati e crea confusione. Ed è doppiamente superfluo perché le due chiavi che forniscono sono già lì, a fissarci in faccia.

Dal momento che non capiscono il RM , o termini relazionali, chiamano tabelle "collegamento" o "mappa" delle tabelle associative. Se hanno un ID campo, sono infatti dei file.

Tabelle di ricerca

ID i campi sono particolarmente Cosa stupida da fare per tabelle di ricerca o di riferimento. La maggior parte di essi ha codici riconoscibili, non è necessario enumerare l'elenco dei codici in essi contenuti, perché i codici sono (dovrebbero essere) univoci.

Inoltre, avere i codici nelle tabelle figlie come FK, è una buona cosa:il codice è molto più significativo e spesso salva un join non necessario:

    SELECT ...
        FROM child_table           -- not the lookup table
        WHERE gender_code = "M"    -- FK in the child, PK in the lookup

invece di:

    SELECT ...
        FROM child_table
        WHERE gender_id = 6        -- meaningless to the maintainer

o peggio:

    SELECT ...
        FROM child_table C         -- that you are trying to determine
        JOIN lookup_table L
            ON C.gender_id = L.gender_id
        WHERE L.gender_code = "M"  -- meaningful, known

Nota che questo è qualcosa che non si può evitare:è necessaria l'unicità nel codice di ricerca e unicità nella descrizione. Questo è l'unico metodo per prevenire duplicati in ciascuno delle due colonne:

    CREATE TABLE gender (
        gender_code  CHAR(2)  NOT NULL,
        name         CHAR(30) NOT NULL

        CONSTRAINT PK 
            PRIMARY KEY ( gender_code )

        CONSTRAINT AK 
            UNIQUE ( name )
        )

Esempio completo

Dai dettagli nella tua domanda, sospetto che tu abbia problemi di sintassi SQL e definizione FK, quindi fornirò l'intera soluzione di cui hai bisogno come esempio (poiché non hai fornito definizioni di file):

    CREATE TABLE user (                 -- Typical Identifying Table
        user_name  CHAR(16) NOT NULL,   -- Short PK
        name_first CHAR(30) NOT NULL,   -- Alt Key.1
        name_last  CHAR(30) NOT NULL,   -- Alt Key.2
        birth_date DATE     NOT NULL    -- Alt Key.3

        CONSTRAINT PK                   -- unique user_name
            PRIMARY KEY ( user_name )

        CONSTRAINT AK                   -- unique person identification
            PRIMARY KEY ( name_last, name_first, birth_date )
        )

    CREATE TABLE sport (                  -- Typical Lookup Table
        sport_code  CHAR(4)  NOT NULL,    -- PK Short code
        name        CHAR(30) NOT NULL     -- AK

        CONSTRAINT PK 
            PRIMARY KEY ( sport_code )

        CONSTRAINT AK 
            PRIMARY KEY ( name )
        )

    CREATE TABLE user_sport (           -- Typical Associative Table
        user_name  CHAR(16) NOT NULL,   -- PK.1, FK
        sport_code CHAR(4)  NOT NULL,   -- PK.2, FK
        start_date DATE     NOT NULL

        CONSTRAINT PK 
            PRIMARY KEY ( user_name, sport_code )

        CONSTRAINT user_plays_sport_fk
            FOREIGN KEY     ( user_name )
            REFERENCES user ( user_name )

        CONSTRAINT sport_occupies_user_fk
            FOREIGN KEY      ( sport_code )
            REFERENCES sport ( sport_code )
        )

Lì, la PRIMARY KEY la dichiarazione è onesta, è una Chiave Primaria; nessun ID; no AUTOINCREMENT; nessun indici extra; nessuna riga duplicata; nessuna aspettativa errata; nessun problema consequenziale.

Modello di dati

Ecco il modello di dati per andare con le definizioni.

  • Esempio di modello di dati sportivi dell'utente

  • Se non sei abituato alla notazione, tieni presente che ogni piccolo segno di spunta, tacca e segno, le linee continue e tratteggiate, gli angoli quadrati e arrotondati, significano qualcosa di molto specifico. Fare riferimento a IDEF1X Notation .

  • Un'immagine vale più di mille parole; in questo caso un'immagine standard di denuncia vale di più; uno cattivo non vale la carta su cui è disegnato.

  • Si prega di controllare attentamente le frasi verbali, esse comprendono una serie di predicati. Il resto dei predicati può essere determinato direttamente dal modello. Se questo non è chiaro, chiedi.