Можно ли вставить строку, но только если одно из значений в таблице не существует?
Я создаю Рассказать другу с реферальными точками для системы электронной торговли, где мне нужно вставить адрес электронной почты друга в таблицу базы данных, но только если он еще не существует в таблице. Это потому, что я не хочу, чтобы больше одного человека получали реферальные баллы после того, как новый клиент зарегистрируется и что-то купит. Поэтому я хочу, чтобы в таблице появлялось только одно электронное письмо.
Я использую PHP 4 и MySql 4.1.






Не уверен, понял ли я, но как насчет
try {
mysql_query($sql);
}
catch(Exception $e) {
}
в сочетании с уникальным индексом поля в MySQL?
если он вызывает исключение, значит, вы знаете, что у вас дублированное поле. Извините, если это не ответ на ваш вопрос ..
Если выбрано исключение, строка не будет добавлена. Можно просто залогиниться, или в улове ничего не делать.
Но с предыдущим запросом он каждый раз вызывал ошибку. Я хотел, чтобы в mySql происходил тихий сбой.
Это хороший подход к решению проблемы за пределами БД, но он не решает проблему в БД, которая, возможно, является тем местом, где об этом следует позаботиться.
@Jeremiah Peschka - Мудрые слова
AFAIK mysql_query() никогда не генерирует исключения при возникновении ошибки SQL, поэтому я не думаю, что это сработало бы как есть?
Если поле электронной почты было первичным ключом, то ограничения в таблице не позволили бы ввести дубликат.
Если столбец является первичным ключом или уникальным индексом:
INSERT INTO table (email) VALUES (email_address) ON DUPLICATE KEY UPDATE
email=email_address
Зная, что мне повезло, есть способ сделать это лучше. Насколько мне известно, в MySQL нет эквивалента "ON DUPLICATE KEY DO NOTHING". Я не уверен насчет бита email = email_Address, вы можете поиграться и посмотреть, работает ли он без необходимости указывать действие. Однако, как кто-то утверждает выше, если у него есть уникальные ограничения, в любом случае ничего не произойдет. И если вы хотите, чтобы все адреса электронной почты в таблице были уникальными, нет причин указывать его как уникальный в определении столбца.
Я установил для электронной почты уникальный ключ в phpMyAdmin, а затем использовал ваш код. И это отлично сработало! Спасибо
Re: нет эквивалента ON DUPLICATE KEY DO NOTHING. См. Решение Тодда. В качестве альтернативы вы, вероятно, могли бы сделать что-то вроде ON DUPLICATE KEY UPDATE email = email, хотя это, безусловно, более расточительно.
Скорее всего что-то вроде:
IF NOT EXISTS(SELECT * FROM myTable WHERE Email=@Email) THEN INSERT INTO blah blah
Это можно свести в один запрос к базе данных.
Это работает, если у вас есть уникальный индекс или первичный ключ в столбце (EmailAddr в этом примере):
INSERT IGNORE INTO Table (EmailAddr) VALUES ('[email protected]')
Используя это, если запись с этим адресом электронной почты уже существует (нарушение дублированного ключа) вместо ошибки, оператор просто не работает и ничего не вставляется.
См. Документы MySql для получения дополнительной информации.
«INSERT IGNORE» - лучший ответ, но REPLACE (dev.mysql.com/doc/refman/5.0/en/replace.html) также является вариантом, если вы хотите повторно вставить строку по какой-либо причине (возможно, триггер временной метки или что-то в этом роде).
Будьте осторожны с REPLACE, увеличивая ваш автоинкремент - под капотом это просто DELETE, INSERT.
MySQL предлагает ЗАМЕНИТЬ НА http://dev.mysql.com/doc/refman/5.0/en/replace.html:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
Небольшая модификация / дополнение к ответу naeblis:
INSERT INTO table (email) VALUES (email_address)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)
Таким образом, вам не нужно бросать туда email=email_address. и, вы получите правильное значение для LAST_INSERT_ID(), если оператор обновится.
Источник: MySQL Документы: 12.2.5.3
Спасибо за ответ, но я не думаю, что это решит мою проблему. Мне нужен один запрос, который либо вставляет строку, либо ничего не делает в случае сбоя.