2016-04-21 4 views
2

Ich füge Daten, die für alle drei Spalten mit INSERT IGNORE eindeutig sind. Wie kann ich die Zeit ausschließen und das Datum überprüfen, wenn es mit den anderen zwei Spalten unten einzigartig ist?INSERT IGNORE für Datum und Ignorieren der Zeit

eindeutiger Index für Spalten: Zeitstempel, Aktion, Wert

Zeitstempel Format: 2016-04-21 13:33:47

Meine Tabelle Beispiel:

2016-04-21 13:33:47, senden, E-Mail

2016-04-20 11:21:32, senden, E-Mail

2016-04-19 17:32:65, senden E-Mail

Was ich versuche zu tun: Wenn ich versuche, unten die Daten einzufügen, sollte es ignoriert werden, da es für die bestehenden Daten ist 2016-04-21, senden, E-Mail.

2016-04-21 19:33:47, senden E-Mail

+0

Übrigens, 2016-04-19 17:32:65 ist kein gültiger Zeitstempel. Ich nehme an, die Sekunden sind ein Tippfehler. –

Antwort

1

Der einzige Weg, eine IGNORE funktionieren, wenn Sie eine oder mehrere Spalten in einem UNIQUE Index haben. In diesem Fall benötigen Sie ein DATE Feld, das von Ihrem DATETIME abgeleitet ist.

Zum Beispiel:

ALTER TABLE my_emails ADD COLUMN sent_date DATE 
CREATE UNIQUE INDEX idx_sent_date ON my_emails (sent_date) 

Dann können Sie es füllen:

UPDATE my_emails SET sent_date=DATE(sent_datetime) 

mit dem, was die Spalten sind. Von diesem Punkt an müssen Sie sicher sein, dass Sie beide Felder ausfüllen.

1

Wenn Sie MySQL 5.7.6 oder höher verwenden, können Sie eine generierte Spalte mit einem eindeutigen Index erstellen.

ALTER TABLE table_name 
ADD COLUMN timestamp_date DATE GENERATED ALWAYS AS (DATE(timestamp)) STORED, 
ADD UNIQUE (timestamp_date, action, value); 

mit einer früheren Version von MySQL, müssen Sie eine Spalte hinzufügen, um das Datum zu speichern und einen Trigger (verfügbar ab Version 5.0.2), sie zu aktualisieren verwenden, wenn Sie neue Datensätze in der Tabelle einzufügen.

ALTER TABLE table_name 
ADD COLUMN timestamp_date DATE; 

CREATE TRIGGER insert_table_name_date BEFORE INSERT ON table_name 
FOR EACH ROW SET NEW.timestamp_date = DATE(NEW.timestamp); 

-- If you already have any data in the table, update it to add the date. 
UPDATE table_name SET timestamp_date = DATE(timestamp_date); 

ALTER TABLE table_name 
ADD UNIQUE (timestamp_date, action, value); 

INSERT INTO table_name(timestamp, action, value) VALUES 
('2016-04-21 13:33:47', 'send', 'email'), 
('2016-04-20 11:21:32', 'send', 'email'), 
('2016-04-19 17:32:55', 'send', 'email'); 

-- 3 row(s) affected 

INSERT INTO table_name(timestamp, action, value) VALUES 
('2016-04-21 19:33:47', 'send', 'email'); 

-- Error Code: 1062. Duplicate entry '2016-04-21-send-email' for key 'timestamp_date' 
+0

Sie benötigen 5.7.8, um diesen Index zu erstellen: "Vor MySQL 5.7.8 können virtuelle Spalten nicht indiziert werden. Ab MySQL 5.7.8 unterstützt InnoDB sekundäre Indizes für virtuelle Spalten." [CREATE TABLE-Syntax] (http://dev.mysql.com/doc/refman/5.7/en/create-table.html) –

+0

@Paul Spiegel Ich kann nicht testen, ich habe keine 5.7.6. Aber mein Verständnis ist, dass ** virtuelle ** generierte Spalten nicht indiziert werden können, aber ** gespeicherte ** generierte Spalten können. –

+0

Sie haben recht: "Eine gespeicherte Spalte benötigt Speicherplatz und kann indiziert werden." Allerdings - Schöne Lösung. –

1

Sie können eine INSERT-SELECT-Anweisung mit konstanten Daten aus einer Dummy-Tabelle verwenden. Auf diese Weise können Sie eine WHERE-Klausel einfügen.

insert into actions (`timestamp`, action, value) 
    select '2016-04-21 19:33:47', 'send', 'email' 
    from (select 1) dummy 
    where not exists (
     select 1 
     from actions 
     where action = 'send' 
      and value = 'email' 
      and date(`timestamp`) = '2016-04-21' 
    ); 

http://sqlfiddle.com/#!9/5882c/1

Die Daten werden nur in der Unterabfrage, wenn die Bedingung keine Streichhölzer hat eingefügt werden.