chiave primaria deve sempre essere firmato?

dato una chiave primaria (identificatore) non sarà inferiore a 0, credo che si dovrebbe sempre essere unsigned?

 

4 Replies
  1. 50

    TL/DR: Sì, ma quasi non importa.

    Incremento automatico aumenta sempre, in modo non potrà mai utilizzare valori negativi. Si potrebbe anche fare senza segno, e si ottiene due volte il range di valori.

    D’altra parte, se la tabella utilizza 231 valori, sarà probabilmente anche l’utilizzo di 232 valori in un breve periodo di tempo, in modo da avere due volte la gamma di valori che non è una grande differenza. È necessario eseguire l’aggiornamento a BIGINT comunque.


    MySQL supporta facoltativo SERIAL tipo di dati (presumibilmente per la compatibilità con PostgreSQL, dal SERIAL non è standard ANSI SQL). Questo tipo di dati è solo scorciatoia che crea un BIGINT UNSIGNED.

    Andare avanti provare:

    CREATE TABLE test.foo (foo_id SERIAL PRIMARY KEY);
    
    SHOW CREATE TABLE test.foo;
    
    CREATE TABLE `test`.`foo` (
      `foo_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`foo_id`),
      UNIQUE KEY `foo_id` (`foo_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 

    Si ottiene lo stesso numero di valori distinti se si dichiara un valore integer con segno o senza segno: 232 per un INT e 264 per un BIGINT. Se il numero non è firmato, si ottengono i valori da 0 al valore massimo meno uno. Se il numero è firmato, si ottengono i valori da -max/2 per max/2-1. In ogni modo, si ottiene lo stesso numero assoluto di valori distinti.

    Ma dal momento che AUTO_INCREMENT inizia a zero di default e incrementi in senso positivo, è più conveniente utilizzare i valori positivi di valori negativi.

    Ma poco importa che si ottiene 2X come molti valori positivi. Qualsiasi tabella che supera il massimo valore intero con segno 231-1 è probabile che continuerà a crescere, così si dovrebbe utilizzare un BIGINT per queste tabelle.

    Sei davvero, davvero, davvero improbabile di allocare più di 263-1 valori di chiave primaria, anche se si elimina tutte le righe e ri-caricare molte volte al giorno.

    • Solo per la massima chiarezza: di SERIE è specificamente un alias per “BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNICO”, come di MySQL 4.1+.
    • I didnt’ ottenere una risposta. Così dovrebbe chiave primaria sempre essere firmati o non firmati?
    • da un lato, sì, di incremento automatico aumenta sempre, in modo non potrà mai utilizzare valori negativi. Si potrebbe anche fare senza segno, e si ottiene due volte il range di valori. Ma, d’altro canto, se vuoi usare 2^31 valori, si sarà probabilmente anche l’utilizzo di 2^32 valori in un paio di mesi, quindi è necessario eseguire l’aggiornamento a BIGINT comunque.
  2. 6

    Perché sono esattamente presumere che una chiave primaria non sarà sotto 0? Che non è un dato di fatto. Credo che stai confondendo con una colonna identity.

    In ogni caso non si dovrebbe fare nessuna differenza apprezzabile in ogni modo, la mappa per il tipo di dati per il tipo di dati che si prevede nella colonna indipendentemente dal fatto che si tratta di una chiave primaria o non.

    • sì intendevo un identificatore. perché dovrebbe essere al di sotto dello zero?
    • ma se ho un unsigned INT, doesnt significa che avrà la doppia quantità di numeri positivi che posso usare?
    • Ti aspettavi di più di 2.147.483.647 record nelle tabelle, spesso? Nello spirito del defunto Doug Adams adeguerò la mia risposta dello stato che ha firmato interi per una colonna di identità sono “per lo più innocuo”
    • MySQL tratta i numeri interi negativi in una chiave primaria maggiore di 0 per la creazione di quello successivo.
    • staticsan – sei sicura di questo? Ho creato una tabella di prova mista positivo e negativo PK valori, e non vedo alcuna tale considerazione dei valori negativi.
  3. 3

    NO – una chiave primaria wont essere sempre unsigned per esempio:

     create table user_status
     (
      status_id tinyint not null primary key,
      name varchar(64) not null,
      msg varchar(255) default null
     )engine=innodb;
    
     insert into user_status values 
        (-99,'banned', 'Account banned'), 
        (-2,'closed', 'Account closed'),
        (-1,'unverified', 'Account not verified'),
        (0,'suspended','Account suspended'),
        (1,'active', null);     

    se questa era una tabella ordini tuttavia mi piacerebbe utilizzare order_id int unsigned

    • spiegare il basso voto
    • Il tuo esempio è probabile (l’ho visto prima). Ma credo che il richiedente è più interessato a una visione ampia spiegazione delle motivazioni per farlo.
    • Stai sovraccaricando l’uso di una chiave primaria. Lo stato dovrebbe essere colonna separata. Questo non è un buon design.
    • tutti dobbiamo scrivere/business logica dell’applicazione che utilizza i dati relazionale che abbiamo memorizzato nel nostro meravigliosamente normalizzati in schemi. Tuttavia, nella mia esperienza, avendo firmato intero chiavi primarie, in particolare su stato o le tabelle del tipo può aiutare a semplificare la logica di business in modo considerevole. Potrebbe non essere un buon design nel tuo libro, ma nel mio funziona alla grande.
    • Apprezzo il mondo non è perfetto, ma utilizzando un cattivo esempio per dimostrare il vostro caso è la diffusione di cattiva progettazione. Cosa succede associato al record di ban di un account? Hai perso l’ID originale. Come si fa a riprendere un account? Vuoi dare una nuova chiave primaria? Forse dicendo che progetti come questi esistono e quindi è possibile che le chiavi primarie sarebbe firmato ma ritengo che questa è una cattiva idea.
    • Si sta modificando semplicemente il user_status_id (foreign key) nella tabella utente a -99. Non cambia nulla altro tranne ora la tua logica di business è impedire che l’account di accesso nel sistema e l’integrità dei relativi dati relazionali ad esempio, gli ordini, i thread, conti, ecc è mantenuto. Penso che hai bisogno di me di aggiungere una tabella utente per il mio esempio 🙂
    • Scusa ho saltato la _status parte del user_status nome e basta leggere user.
    • Comunque, direi che questo è stato overnormalization. Basta usare una stringa di stato nella tabella utente che ti dice lo stato, senza dover fare riferimento a questa tabella. Le stringhe possono essere indicizzati senza perdita di prestazioni. Il messaggio deve essere contenuta in applicazione (a meno che, naturalmente, l’intera applicazione è scritto nel db quindi credo che funziona). Credo che il tuo ragionamento è che altro che 1 è un account inattivo.
    • Vorrei rimuovere il downvote ma è bloccato a meno che non si modifica la risposta.

  4. 2

    dato una chiave primaria (identificatore) non sarà al di sotto di 0

    Presumo da quello economico che la vostra chiave primaria anche auto-incrementi.

    Se lo fa, allora è molto sensibile per garantire la vostra colonna non è firmato, per il motivo descritto in MySQL manuale:

    Una colonna AUTO_INCREMENT, funziona correttamente solo se contiene solo valori positivi. L’inserimento di un numero negativo è considerato come l’inserimento di un grande numero positivo. Questo viene fatto per evitare problemi di precisione quando i numeri di “a capo” da positivo a negativo e anche per garantire che non accidentalmente ottenere un AUTO_INCREMENT colonna che contiene 0.

    Se si inseriscono i numeri negativi in un incremento automatico di colonna, poi si sono probabilmente la soluzione di un problema in modo sbagliato.

Lascia un commento