неділя, 19 вересня 2010 р.

Видалення рядків із таблиці в MySql. Error Code: 1093, 1175

Маю значний досвід програмування в MS SQL Server 2000. Зараз вивчаю MySql. Опишу проблему, яка виникла під час видалення рядків із таблиці.

Є таблиця:

CREATE TABLE `menu` (
`MenuID` int(11) NOT NULL AUTO_INCREMENT,
`MenuIDP` int(11) NOT NULL,
`Menu` varchar(100) NOT NULL,
PRIMARY KEY (`MenuID`),
KEY `IX_MenuIDP` (`MenuIDP`),
) ENGINE=InnoDB AUTO_INCREMENT=407 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

В СУБД MS SQL Server вкладений запит виконувався без проблем:

delete from menu where `MenuIDP` not in(select `MenuID` from menu);

"Видали, будь ласка, всі рядки із таблиці menu, в яких значення поля `MenuIDP` не співпадають із жодним із значень поля `MenuID`". Погодьтеся, що інструкція лаконічна і зрозуміла.

MySql на такий запит чемно повернув

Error Code: 1093
You can't specify target table 'menu' for update in FROM clause

Вивчаючи досвід колег в Internet, дізнався, що MySql не може видалити рядки із таблиці, яка тимчасово блокується командою select. Очевидно в цьому є деякий смисл.
Если вам нужно чтобы заработал ваш запрос - могу сказать, что mysql можно перехитрить делая селект не из самой таблицы, а присоединяя ее к чему либо (например к select 1 as k) по right outer join.(Удаление данных из таблицы MySql)
Хитрити із MySql я не став, а скористався декількома командами із використанням тимчасової таблиці:

   1:  /* створити тимчасову таблицю */
   2:  create temporary table ForRowsDelete(`MenuID` int not null);
   3:  /* вставити код рядків, які потрібно видалити, у тимчасову таблицю */
   4:  insert into ForRowsDelete(`MenuID`)
   5:  select `MenuID` from menu where `MenuIDP` not in(select `MenuID` from menu);
   6:  /* видалити із таблиці menu */
   7:  delete from menu where `MenuID` in(select `MenuID` from ForRowsDelete);
   8:  /* видалити тимчасову таблицю */
   9:  drop temporary table ForRowsDelete;

Багато тексту, зате покроково.

Інструкція 7 чемно повернула:

Error Code: 1175
You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

Виявляється, що MySql просить, щоб після WHERE було вказано індексоване поле незалежно від того, чи потрібно воно для запиту. Але ж поле `MenuID` є PRIMARY?!

В інструкцію 7 додав після WHERE "and `MenuIDP`>0":

delete from menu where `MenuID` in(select `MenuID` from ForRowsDelete) and `MenuIDP`>0;

Такий підхід до видалення даних в MySql забезпечує насамперед високу швидкодію і безпеку інформації. Не сперечаюся.

Update 20.09.2010

Щодо Error Code: 1175. Як виявилося, консольний режим пропускав запити на видалення. Помилку видавала MySql WorkBench 5.2.27CE. Вивчаючи цю IDE, знайшов те, що потрібно.


Достатньо відключити у Edit -> Preferences ... -> SQL editor опцію Forbid UPDATE and DELETE statements without a WHERE clause (safe updates). Але за безпеку відповідати будете самостійно.

неділя, 12 вересня 2010 р.

Паттерн для перевірки правильності запису електронної пошти

Вивчаю регулярні вислови. Процедура перевірки правильності запису електронної адреси є без сумніву необхідна.

В код програми я включив паттерн, який пропонує бібліотека MSDN:

string _pattern = "^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$"

Пропозиція Microsoft на перший погляд універсальна. Шаблон аналізує не лише ім`я домена, але і IP-адреси на зразок j_9@[129.126.118.1]. Але виявилося, що паттерн вважає неправильними адреси поштового сервісу www.i.ua (my-email@i.ua). Очевидно, назва домену із однієї літери є нестандартною. Але ж сервіс існує?

Проблемною можна вважати передостанню частину паттерну: "...([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+...". Спочатку відбувається пошук одного символа із діапазону "[0-9a-zA-Z]" (тобто від "0" до "9", або від "a" до "z", або від "A" до "Z"). Наступними можуть бути-не-бути дефіси або символи з діапазону "[0-9a-zA-Z]" (частина "[-\w]*"). Завершує будь який символ із "[0-9a-zA-Z]". Пошуковий текст повинен закінчитися крапкою.

Дивно, але за таким паттерном правильними вважаються адреси вигляду myemail@server-----x.com.

Передостанню частину я переписав як "...([0-9a-zA-Z]+[-]?[0-9a-zA-Z]*\.)+...". Пропоную один або декілька символів "[0-9a-zA-Z]+", потім відсутність або один дефіс "[-]?", за яким слідує відсутність або декілька символів "[0-9a-zA-Z]*". Шаблон завершується крапкою "\.". Весь вираз повторюється один або декілька разів - для цього є знак "+" в кінці рядка.

Загальний вигляд удосконаленого мною патерну перевірки правильності електронної пошти:

string _pattern = @"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z]+[-]?[0-9a-zA-Z]*\.)+[a-zA-Z]{2,6}))$";

Отже, не порушуючи особливо логіки базового шаблону, поштові адреси із сервісу www.i.ua вважаються правильними, домени із n-ою кількістю дефісів - неправильними.


З повагою, Юрій Оснадчук.

Література:
  1. Практическое руководство. Проверка строк на соответствие формату электронной почты.
  2. Регулярные выражения.
  3. Сервіс тестування регулярних висловів realcode.ru

неділя, 15 серпня 2010 р.

Інша сторона життя ...

Цей блог міститиме інформацію про особливості розробки та впровадження системи управління навчальним процесом "Універсум", - програми, яка з 2004 року активно допомагає керувати навчальним процесом на соціально-психологічному факультеті Житомирського державного університету імені Івана Франка.

Автори програми:
  • Олександр Леонідович Музика, - кандидат психологічних наук, доцент, декан соціально-психологічного факультету ЖДУ імені Івана Франка, мудрий керівник, активний психолог-дослідник і просто чудова людина.
  • Оснадчук Юрій Олегович (тобто я), асистент кафедри соціальної та практичної психології, неофіційний програміст факультету.