Domanda

Come posso creare in modo efficiente un indice univoco su due campi in una tabella come questa: crea la tabella t (un numero intero, un numero intero b);

dove una combinazione unica di due numeri diversi non può apparire più di una volta sulla stessa riga della tabella.

In parole d'ordine se esiste una riga tale che a = 1 e b = 2, non può esistere un'altra riga dove a = 2 e b = 1 o a = 1 e b = 2. In altre parole, due numeri non possono apparire insieme più di una volta in nessun ordine.

Non ho idea di come venga chiamato un tale vincolo, quindi il nome "indice unilaterale fronte / retro" nel titolo.

Aggiorna : se ho una chiave composita sulle colonne (a, b) ed esiste una riga (1,2) nel database, è possibile inserire un'altra riga (2,1 ) senza errori. Quello che sto cercando è un modo per impedire che la stessa coppia di numeri venga utilizzata più di una volta in qualsiasi ordine ...

È stato utile?

Soluzione

Che ne dici di controllare cosa succede nella tabella in modo da memorizzare sempre il numero più piccolo nella prima colonna e quello più grande nella seconda? Finché "significa" ovviamente la stessa cosa. Probabilmente è meno costoso farlo prima ancora che arrivi al database.

Se ciò è impossibile, è possibile salvare i campi così come sono ma farli duplicare in ordine numerico in due ALTRI campi, su cui creare la chiave primaria (pseudo code-ish):

COLUMN A : 2
COLUMN B : 1

COLUMN A_PK : 1  ( if new.a < new.b then new.a else new.b )
COLUMN B_PK : 2  ( if new.b > new.a then new.b else new.a )

Questo potrebbe essere facilmente fatto con un trigger (come nella risposta di Ronald) o gestito più in alto, nell'applicazione.

Altri suggerimenti

Penso che questo possa essere fatto solo usando un trigger FOR INSERT (in combinazione con un vincolo univoco sulle due colonne). Non sono molto fluente nella sintassi di MySql (il mio T-SQL è migliore), quindi immagino che quanto segue conterrà alcuni errori:

Modifica: ripulita la sintassi in modo che funzioni per MySQL. Inoltre, tieni presente che probabilmente vorrai metterlo anche come un trigger PRIMA DELL'AGGIORNAMENTO (con un nome diverso ovviamente).

Inoltre, questo metodo si basa sull'avere una chiave primaria o univoca sui due campi (cioè questo trigger controlla solo che non esiste già il contrario). Non sembra esserci alcun modo per lanciare un errore da un grilletto, quindi oso dire che questo è buono come si arriva.

CREATE TRIGGER tr_CheckDuplicates_insert
BEFORE INSERT ON t
FOR EACH ROW
BEGIN
    DECLARE rowCount INT;
    SELECT COUNT(*) INTO rowCount
                   FROM t
                   WHERE a = NEW.b AND b = NEW.a;

    IF rowCount > 0 THEN
        -- Oops, we need a temporary variable here. Oh well.
        -- Switch the values so that the key will cause the insert to fail.
        SET rowCount = NEW.a, NEW.a = NEW.b, NEW.b = rowCount;
    END IF;
END;

In Oracle è possibile utilizzare un indice basato sulle funzioni come questo:

create unique index mytab_idx on mytab (least(a,b), greatest(a,b));

Non conosco mySQL, ma forse qualcosa di simile è possibile? Ad esempio, è possibile aggiungere 2 nuove colonne leastab e greatestab alla tabella, con un trigger per mantenerle rispettivamente con i valori minimo (a, b) e maggiore (a, b), quindi creare un indice univoco su (leastab , greatestab).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top