Вставить значения в таблицу базы данных, избегая дубликатов [дублировать]

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Например:

Предположим, что у вас есть класс с именем Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Как видно из вышеприведенного кода, оператор Student s - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется выполнение инструкции s.GetFullName (), она выкинет исключение NullReferenceException.

275
задан Piskvor 2 July 2010 в 10:43
поделиться

15 ответов

Я на самом деле не предлагаю, чтобы вы это делали, поскольку индекс UNIQUE, предложенный 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  |
+----+--------+-----------+------+

И так далее ...

374
ответ дан Mike 25 August 2018 в 01:30
поделиться
  • 1
    Спасибо, что помогли. Моя фактическая проблема намного сложнее, и столбец просто не может быть уникальным, и я не могу зависеть от первичного ключа. Но это именно то, что я искал. – Rupert 2 July 2010 в 11:41
  • 2
    @Piskovar: Согласен. @Rupert: вы должны индексировать столбец, указанный во внутреннем операторе select (name, в этом случае), если это вообще возможно. Также обратите внимание, что вы можете сделать SELECT 'John', 'Doe', '022' FROM table_listnames вместо SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp - но это будет работать, только если table_listnames уже содержит одну или несколько строк. Я сомневаюсь, что скорость отличается от других, так что, вероятно, это не проблема. – Mike 2 July 2010 в 11:54
  • 3
    @VijayRamamurthy: Это работает, потому что вы вставляете результат инструкции Select. Внимательно прочтите запрос - & gt; Оператор WHERE относится к запросу SELECT. Запрос Select возвращает одну строку данных (данные вставлены) или вообще нет данных (ничего не вставлено) – Philipp 27 September 2013 в 15:42
  • 4
    Это не работает, если вы хотите вставить одно и то же значение дважды в разные поля (например, SELECT 'Humbert', 'Humbert', '1' во внутреннем выборе). Я получаю ERROR 1060 (42S21): Duplicate column name – cburgmer 10 October 2013 в 13:25
  • 5
    @cburgmer У меня такая же проблема #1060 - Duplicate column name. Вы нашли решение? Изменить: нашел. Добавьте за каждым значением AS: SELECT * FROM (SELECT 'Rupert' as name, 'Rupert' as friend, '022' as number) AS tmp – Kai Noack 17 February 2014 в 17:14

Этот запрос может быть использован в PHP-коде.

У меня есть столбец идентификатора в этой таблице, поэтому мне нужно проверить дублирование для всех столбцов, кроме этого столбца 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

1
ответ дан Andrew 25 August 2018 в 01:30
поделиться

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

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

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

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';
10
ответ дан Arash Hatami 25 August 2018 в 01:30
поделиться

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

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;
12
ответ дан Brian Hooper 25 August 2018 в 01:30
поделиться

Этот запрос работает хорошо:

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 ;

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

8
ответ дан dakab 25 August 2018 в 01:30
поделиться
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 )
4
ответ дан Greg the Incredulous 25 August 2018 в 01:30
поделиться

У меня была проблема, и метод, с которым Майк советовал отчасти отчасти, имел ошибку 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 выбрал имена столбцов дубликатов, и я написал код в этом синтаксисе, и он отлично работал,

3
ответ дан Hovhannes Babayan 25 August 2018 в 01:30
поделиться

Работа:

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');
43
ответ дан Mahbub Tito 25 August 2018 в 01:30
поделиться
  • 1
    Это работает только для баз данных Oracle? ru.wikipedia.org/wiki/DUAL_table Этот вопрос касается, в частности, MySQL! – Highly Irregular 4 October 2016 в 07:55
  • 2
    Я не тестирую базу данных Oracle. Он отлично работает в MySQL и тестируется. – Mahbub Tito 16 October 2016 в 04:15
  • 3
    Я так как узнал "двойной" доступен в MySQL, но не в MariaDB, ветке с открытым исходным кодом MySQL – Highly Irregular 16 October 2016 в 07:53
  • 4
    Из ссылки @ HighlyIrregular's wikipedia «Несколько других баз данных (включая Microsoft SQL Server, MySQL, PostgreSQL, SQLite и Teradata) позволяют полностью отказаться от предложения FROM, если таблица не нужна. Это позволяет избежать необходимости в любой фиктивной таблице. & Quot; Тот же запрос работает в MySql (5.7, если это имеет значение) без FROM DUAL. – stannius 14 May 2018 в 19:05
INSERT IGNORE INTO `mytable`
SET `field0` = '2',
`field1` = 12345,
`field2` = 12678;

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

----Untested----
17
ответ дан Montaser El-sawy 25 August 2018 в 01:30
поделиться
  • 1
    он не работал для меня, INSERT IGNORE INTO emAssignedTagsForEvent SET eventId = '2', defaultTagId = '1'; – pitu 7 June 2014 в 06:29
  • 2
    Похож на смесь синтаксисов вставки и обновления. Вы имеете в виду INSERT IGNORE INTO `mytable` (`field0`, `field1`, `field2`) values ('2', 12345, 12678);? – Hobo 22 October 2014 в 13:33
  • 3
    @Hobo From MySQL Manual dev.mysql.com/doc/refman/5.7/en/insert.html Синтаксис INSERT: может быть INSERT [...] IGNORE INTO mytable VALUES ... или INSERT [...] IGNORE INTO mytable SET col_name={expr | DEFAULT},... – Shirkam 26 July 2017 в 06:43
  • 4
    «Если вы используете модификатор IGNORE, ошибки, возникающие при выполнении инструкции INSERT, игнорируются. & quot ;. Так что в основном вы ничего не решили. – Marcelo Agimóvel 26 December 2017 в 13:25

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

name VARCHAR(20),
UNIQUE (name)

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

INSERT IGNORE INTO train
set table_listnames='Rupert'
11
ответ дан obsessiveCookie 25 August 2018 в 01:30
поделиться

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

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

  • normal INSERT (и обрабатывать ошибку, если имя уже существует)
  • INSERT IGNORE (который не будет выдавать предупреждение (вместо ошибки), если имя уже существует)
  • INSERT ... ON DUPLICATE KEY UPDATE (который будет выполните UPDATE в конце, если имя уже существует, см. документацию )
241
ответ дан Piskvor 25 August 2018 в 01:30
поделиться
  • 1
    Благодарим вас за список доступных опций. INSERT IGNORE помог мне. – Xynariz 11 February 2014 в 19:48
  • 2
    Спасибо youuuu, 3,5 года спустя и все еще помогая людям :). – Andrew 27 February 2014 в 01:29
  • 3
    5 лет спустя и все еще помогая ppl :) – motan 20 May 2015 в 11:55
  • 4
    когда INSERT игнорируется, значение auto_increment увеличивается ... – illusionJJ 28 April 2016 в 13:12
  • 5
    если вам нужно получить предупреждающее сообщение, вы можете впоследствии сделать mysql> show warnings\G – fiorentinoing 20 October 2016 в 18:59

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

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

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

19
ответ дан sdesvergez 25 August 2018 в 01:30
поделиться
  • 1
    Но он обновляет запись (смотрите на затронутые строки) – Azmeer 5 November 2015 в 06:21
  • 2
    для предотвращения его вам нужно создать уникальный индекс, более подробную информацию здесь: link – Azmeer 5 November 2015 в 06:34

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

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 из другой таблицы. С уважением, Иван

4
ответ дан Sgoettschkes 25 August 2018 в 01:30
поделиться
  • 1
    Что такое «двойное»? Встроенное ключевое слово? Я просто не вижу разницы с тем, что сказал Брайан. EDIT: Дальнейшее расследование стало смешанным и противоречивым (?) Результатом. На странице SQL DUAL table говорится, что MySQL не поддерживает таблицы DUAL, руководство MySQL говорит, что это так. Мой собственный тест показывает, что это не так, поскольку он дает сообщения unknown table status: TABLE_TYPE, хотя запрос дал результат. Вероятно, потому что MySQL не требует предложения FROM DUAL? – not2qubit 29 October 2013 в 20:55

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

3
ответ дан User 1034 25 August 2018 в 01:30
поделиться
  • 1
    вещь я не могу установить ее на первичный или уникальный – Rupert 2 July 2010 в 10:41

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

Обратите внимание: мне нужно было определять имя везде, где 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: CREATE TABLE names (OID int (11) NOT NULL AUTO_INCREMENT, name varchar (32) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (OID), UNIQUE KEY name_UNIQUE (name)) ENGINE = InnoDB AUTO_INCREMENT = 1;

или

MSSQL: CREATE TABLE [имена] ([OID] INT IDENTITY (1, 1 ) NOT NULL, [имя] NVARCHAR (32) NOT NULL, ПЕРВИЧНАЯ КЛАВИАТУРА ([OID] ASC)); CREATE UNIQUE NONCLUSTERED INDEX [Index_Names_Name] ON [имена] ([имя] ASC);

2
ответ дан Waldemar 25 August 2018 в 01:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: