MySQL: вставить запись, если не существует в таблице

Я пытаюсь выполнить следующий запрос:

INSERT INTO table_listnames (name, address, tele)
VALUES ('Rupert', 'Somewhere', '022')
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name='value'
);

но это возвращает ошибку. В принципе, я не хочу вставлять запись, если поле " Имя " записи уже существует в другой записи - Как проверить, является ли новое имя уникальным?

15 ответов


Я на самом деле не предлагаю вам делать это, как как полагают Piskvor и другим-это гораздо лучший способ сделать это, но вы можете на самом деле делать то, что вы пытались:

CREATE TABLE `table_listnames` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `address` varchar(255) NOT NULL,
  `tele` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

вставить запись:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

SELECT * FROM `table_listnames`;

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
+----+--------+-----------+------+

попробуйте вставить ту же запись еще раз:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;

Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
+----+--------+-----------+------+

вставить другую запись:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'John'
) LIMIT 1;

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

SELECT * FROM `table_listnames`;

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
|  2 | John   | Doe       | 022  |
+----+--------+-----------+------+

и так далее...


вставка не позволяет WHERE синтаксис.

что вы можете сделать: создать UNIQUE INDEX на поле, которое должно быть уникальным (name), а затем использовать:

  • нормальный INSERT (и обработать ошибку, если имя уже существует)
  • INSERT IGNORE (который будет прекращена вызовите предупреждение (вместо ошибки), если имя уже существует)
  • INSERT ... ON DUPLICATE KEY UPDATE (который будет выполнять UPDATE в конце, если имя уже существует, документации)

работает :

INSERT INTO users (full_name, login, password) 
  SELECT 'Mahbub Tito','tito',SHA1('12345') FROM DUAL
WHERE NOT EXISTS 
  (SELECT login FROM users WHERE login='tito');

MySQL предоставляет очень милое решение:

REPLACE INTO `table` VALUES (5, 'John', 'Doe', SHA1('password'));

очень прост в использовании, так как вы объявили уникальный первичный ключ (здесь со значением 5).


INSERT IGNORE INTO `mytable`
SET `field0` = '2',
`field1` = 12345,
`field2` = 12678;

здесь запрос mysql, который вставляет записи, если не существует и будет игнорировать существующие подобные записи.

----Untested----

Если вы действительно не можете получить уникальный индекс в таблице, вы можете попробовать...

INSERT INTO table_listnames (name, address, tele)
    SELECT 'Rupert', 'Somewhere', '022'
        FROM some_other_table
        WHERE NOT EXISTS (SELECT name
                              FROM table_listnames
                              WHERE name='Rupert')
        LIMIT 1;

чтобы преодолеть подобную проблему, я сделал таблицу, которую я вставляю, чтобы иметь уникальный столбец. Используя Ваш пример, при создании у меня было бы что-то вроде:

name VARCHAR(20),
UNIQUE (name)

а затем используйте следующий запрос при вставке в него:

INSERT IGNORE INTO train
set table_listnames='Rupert'

Вы можете легко использовать следующим образом :

INSERT INTO ... ON DUPLICATE KEY UPDATE ...

таким образом, вы можете вставить новая raw и если у вас есть дубликаты данных, замените определенный столбец ( лучшие столбцы-это временные метки ).
Например :

CREATE TABLE IF NOT EXISTS Devices (
  id         INT(6)       NOT NULL AUTO_INCREMENT,
  unique_id  VARCHAR(100) NOT NULL PRIMARY KEY,
  created_at VARCHAR(100) NOT NULL,
  UNIQUE KEY unique_id (unique_id),
  UNIQUE KEY id (id)
)
  CHARACTER SET utf8
  COLLATE utf8_unicode_ci;

INSERT INTO Devices(unique_id, time) 
VALUES('$device_id', '$current_time') 
ON DUPLICATE KEY UPDATE time = '$current_time';

этот запрос работает правильно:

INSERT INTO `user` ( `username` , `password` )
    SELECT * FROM (SELECT 'ersks', md5( 'Nepal' )) AS tmp
    WHERE NOT EXISTS (SELECT `username` FROM `user` WHERE `username` = 'ersks' 
    AND `password` = md5( 'Nepal' )) LIMIT 1

и вы можете создать таблицу, используя следующий запрос:

CREATE TABLE IF NOT EXISTS `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(30) NOT NULL,
    `password` varchar(32) NOT NULL,
    `status` tinyint(1) DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Примечание: создайте таблицу, используя второй запрос, прежде чем пытаться использовать первый запрос.


Брайан Хупер : Вы почти попали в точку, но у вас есть ошибка в вашем synatx. Ваша вставка никогда не будет работать. Я тестировал свою базу данных и вот правильный ответ:

INSERT INTO podatki (datum,ura,meritev1,meritev1_sunki,impulzi1,meritev2,meritev2_sunki,impulzi2)
            SELECT '$datum', '$ura', '$meritve1','$sunki1','$impulzi1','$meritve2','$sunki2','$impulzi2'
                FROM dual
                WHERE NOT EXISTS (SELECT datum,ura
                                      FROM podatki
                                      WHERE datum='$datum' and ura='$ura'

Я даю вам мой пример y таблица. Вставка почти такая же, как написал Бьян Хупер, за исключением того, что я поставил select FROM DUAL ont из другой таблицы. СДР с уважением, Иван


insert into customer_keyskill(customerID, keySkillID)
select  2,1 from dual
where not exists ( 
    select  customerID  from customer_keyskill 
    where customerID = 2 
    and keySkillID = 1 )

вы вставляете, не обновляя результат. Можно определить столбец name в основном столбце или задать его как уникальный.


У меня была проблема, и метод, который Майк посоветовал, работал частично, у меня была ошибка Dublicate Column name = '0', и изменил синтаксис вашего запроса как это'

     $tQ = "INSERT  INTO names (name_id, surname_id, sum, sum2, sum3,sum4,sum5) 
                SELECT '$name', '$surname', '$sum', '$sum2', '$sum3','$sum4','$sum5' 
FROM DUAL
                WHERE NOT EXISTS (
                SELECT sum FROM names WHERE name_id = '$name' 
AND surname_id = '$surname') LIMIT 1;";

проблема заключалась в именах столбцов. sum3 был равен sum4 и mysql бросил имена столбцов дубликата, и я написал код в этом синтаксисе, и он работал отлично,


у меня была аналогичная проблема, и мне нужно было вставить несколько, если не существует. Итак, из приведенных выше примеров я пришел к этой комбинации... он здесь на случай, если кому-то понадобится.

уведомления: Я должен был определить имя везде, как требовал MSSQL... MySQL работает с * тоже.

INSERT INTO names (name)
SELECT name
FROM
(
  SELECT name
  FROM
  (
     SELECT 'Test 4' as name
  ) AS tmp_single
  WHERE NOT EXISTS
  (
     SELECT name FROM names WHERE name = 'Test 4'
  )
  UNION ALL
  SELECT name
  FROM
  (
     SELECT 'Test 5' as name
  ) AS tmp_single
  WHERE NOT EXISTS
  (
     SELECT name FROM names WHERE name = 'Test 5'
  )
) tmp_all;

в MySQL: СОЗДАТЬ ТАБЛИЦУ names ( OID инт(11) не null типа AUTO_INCREMENT, name varchar (32) сопоставить utf8_unicode_ci не NULL, ПЕРВИЧНЫЙ КЛЮЧ (OID), УНИКАЛЬНЫЙ КЛЮЧ name_UNIQUE (name) ) Двигатель=InnoDB в типа AUTO_INCREMENT=1;

или

в MSSQL: Создать таблицу [имена] ( [OID] INT IDENTITY (1, 1) NOT NULL, [name] NVARCHAR (32) NOT NULL, КЛАСТЕРИЗОВАННЫЙ ПЕРВИЧНЫЙ КЛЮЧ ([OID] ASC) ); Создать уникальный некластеризованный индекс [Index_Names_Name] на [names] ([name] ASC);


этот запрос можно использовать в PHP-код.

у меня есть столбец ID в этой таблице, поэтому мне нужно проверить дублирование для всех столбцов, кроме этого столбца ID:

#need to change values
SET @goodsType = 1, @sybType=5, @deviceId = asdf12345SDFasdf2345;    


INSERT INTO `devices` (`goodsTypeId`, `goodsId`, `deviceId`) #need to change tablename and columnsnames
SELECT * FROM (SELECT @goodsType, @sybType, @deviceId) AS tmp
WHERE NOT EXISTS (
    SELECT 'goodsTypeId' FROM `devices` #need to change tablename and columns names
    WHERE `goodsTypeId` = @goodsType
        AND `goodsId` = @sybType
        AND `deviceId` = @deviceId
) LIMIT 1;

и теперь новый элемент будет добавлен только в случае, если не существует строки со значениями, настроенными в SET строка