SQL - ЯКЩО ІСНУЄ ОНОВЛЕННЯ ІНШЕ ВСТАВИТИ В


77

Я намагаюся зробити INSERTпідписників у моїй базі даних, але IF EXISTSце має UPDATEбути рядок, ELSE INSERT INTOновий рядок.

Звичайно, я підключаюся до бази даних спочатку і GETз $name, $emailі $birthdayз рядка url.

$con=mysqli_connect("localhost","---","---","---");
// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }

$name=$_GET['name']; 
$email=$_GET['email'];
$birthday=$_GET['birthday'];

Це працює, але просто додає новий рядок;

mysqli_query($con,"INSERT INTO subs (subs_name, subs_email, subs_birthday)
VALUES ('$name', '$email', '$birthday')");

mysqli_close($con);

Ось що я спробував;

mysqli_query($con,"INSERT INTO subs (subs_name, subs_email, subs_birthday)
VALUES '$name', '$email', '$birthday'
ON DUPLICATE KEY UPDATE subs_name = VALUES($name), subs_birthday = VALUES($birthday)");
mysqli_close($con);

і

mysqli_query($con,"IF EXISTS (SELECT * FROM subs WHERE subs_email='$email')
    UPDATE subs SET subs_name='$name', subs_birthday='$birthday' WHERE subs_email='$email'
ELSE
    INSERT INTO subs (subs_name, subs_email, subs_birthday) VALUES ('$name', '$email', '$birthday')");
mysqli_close($con);

і

mysqli_query($con,"IF NOT EXISTS(SELECT * FROM subs WHERE subs_email='$email')
Begin
INSERT INTO subs (subs_name, subs_email, subs_birthday)
VALUES ('$name', '$email', '$birthday')
End");
mysqli_close($con);

Але ніхто з них не працює, що я роблю не так?

Будь-яка допомога дуже вдячна!


2
у вас є унікальні обмеження на вашому столі?
Джон Ву

Відповіді:


200
  1. Створіть UNIQUEобмеження для вашого subs_emailстовпця, якщо воно ще не існує:

    ALTER TABLE subs ADD UNIQUE (subs_email)
    
  2. Використання INSERT ... ON DUPLICATE KEY UPDATE:

    INSERT INTO subs
      (subs_name, subs_email, subs_birthday)
    VALUES
      (?, ?, ?)
    ON DUPLICATE KEY UPDATE
      subs_name     = VALUES(subs_name),
      subs_birthday = VALUES(subs_birthday)
    

Ви можете використовувати функцію VALUES (col_name) в реченні UPDATE для посилання на значення стовпців з частини INSERT розділу INSERT ... ON DUPLICATE KEY UPDATE - dev.mysql.com

  1. Зверніть увагу, що я використовував заповнювачі параметрів замість рядкових літералів, оскільки насправді слід використовувати параметризовані оператори для захисту від атак введення SQL .

Ти да Чоловіче! Працює як оберіг, тепер шукає спосіб захистити це від ін’єкцій. Я надсилаю дані в базу даних після того, як люди підтвердять свою підписку на розсилку з параметрами, розміщеними в рядку. Будь-яка ідея, як це забезпечити? Thnx
Лоуренс Купер

1
@RehbanKhatri: О, вибачте, я думав, ви мали на увазі в VALUES()пункті. VALUES()Функція просто приймає ім'я стовпця, значення якого з VALUES()пункту ви хочете використовувати: це просто скорочена , щоб перешкодити вам повторювати себе; вам не потрібно ним користуватися. Ви можете просто використовувати свою функцію в SETреченні, якщо хочете, наприклад SET column = MYFUNCTION().
eggyal

1
Мммм, що має сенс, я просто прочитав статтю про це, можливо, стаття помилкова. percona.com/blog/2010/07/14 / ...
amdev

1
@amdev: Це цікава стаття, яка заглиблюється в деталі дуже низького рівня API механізму зберігання даних MySQL, про які я не знав, тож дякую за те, що ви пришвидшили роботу. Однак я все-таки вважаю за краще висловити свою бажану логіку якомога чіткіше, щоб допомогти в майбутньому ремонтопридатності: лише якщо інші вищезазначені занепокоєння виявляться неактуальними і це спричиняє суттєвий вплив на ефективність, я б міг перейти до того, REPLACEколи я справді маю намір оновити. Згадайте сентенцію Кнута: " передчасна оптимізація - корінь усього зла" .
eggyal

3
@joseph: " З ON DUPLICATE KEY UPDATE, значення рядків, на які впливає рядок, дорівнює 1, якщо рядок вставлено як новий рядок, 2, якщо існуючий рядок оновлено, і 0, якщо для існуючого рядка встановлено поточні значення. "
eggyal

-2

Спробуйте це:

INSERT INTO `center_course_fee` (`fk_course_id`,`fk_center_code`,`course_fee`) VALUES ('69', '4920153', '6000') ON DUPLICATE KEY UPDATE `course_fee` = '6000';

Цей скрипт SQL має таблиці / стовпці, не пов’язані зі схемою OP
Єгор Андросов,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.