C, PHP, VB, .NET

Дневникът на Филип Петров


* Регулярни изрази в MySQL

Публикувано на 21 май 2015 в раздел Бази от Данни.

Имаме таблица, в която ще съхраняваме потребителски имена и пароли. Искаме да направим така, че СУБД да валидира данните, които се въвеждат в базата от данни. Например искаме имената да са съставени само от малки букви и цифри, от 4 до 32 символа, а паролите да са от 6 до 64 символа, като задължително има поне една малка, поне една главна буква и поне една цифра. Дадената таблица е следната:

CREATE TABLE users(
  id SERIAL PRIMARY KEY,
  user VARCHAR(32) NOT NULL UNIQUE,
  pass VARCHAR(64) NOT NULL
);

Лесно можем да гарантираме чрез тригери, че в потребителското име няма да има главни букви, ако просто ги превръщаме винаги в малки:

CREATE TRIGGER usernameCheck
BEFORE INSERT ON users FOR EACH ROW
BEGIN
  SET NEW.user = LOWER(NEW.user);
END;

Аналогично трябва да направим тригер за UPDATE. Дължините също не са проблем. Вътре в тригера добавяме условие:

IF(CHAR_LENGTH(NEW.user) NOT BETWEEN 4 AND 32
       OR
   CHAR_LENGTH(NEW.pass) NOT BETWEEN 6 AND 64)
THEN 
   SIGNAL SQLSTATE '45000'
   SET message_text = "Username or password too short";
END IF;

Това обаче не гарантира допълнителните условия - потребителското име трябва да е САМО от малки букви и цифри, т.е. други символи не са позволени. За решението на тази задача MySQL ни позволява да използваме регулярни изрази:

IF(NEW.user NOT REGEXP '^[a-z0-9]+$')
THEN
   SIGNAL SQLSTATE '45000'
   SET message_text = "Username must be only letters and digits";
END IF;

Досещате се, че условието за дължина на низа може да бъде обединено с регулярния израз без проблем като той стане '^[a-z0-9]{4,32}$'. Абсолютно по аналогичен начин ще направим и проверката за паролата:

IF(NEW.pass NOT REGEXP '[a-z]'
     OR
   NEW.pass NOT REGEXP '[A-Z]'
     OR
   NEW.pass NOT REGEXP '[0-9]')
THEN
   SIGNAL SQLSTATE '45000'
   SET message_text = "Password must have uppercase, lowercase letter and a digit;
END IF;

Ето и кода на готовия тригер:

CREATE TRIGGER usernameInsertCheck
BEFORE INSERT ON users FOR EACH ROW
BEGIN
SET NEW.user = LOWER(NEW.user);

IF(CHAR_LENGTH(NEW.user) NOT BETWEEN 4 AND 32
       OR
   CHAR_LENGTH(NEW.pass) NOT BETWEEN 6 AND 64)
THEN 
   SIGNAL SQLSTATE '45000'
   SET message_text = "Username or password too short";
END IF;

IF(NEW.user NOT REGEXP '^[a-z0-9]+$')
THEN
   SIGNAL SQLSTATE '45000'
   SET message_text = "Username must be only letters and digits";
END IF;

IF(NEW.pass NOT REGEXP '[a-z]'
     OR
   NEW.pass NOT REGEXP '[A-Z]'
     OR
   NEW.pass NOT REGEXP '[0-9]')
THEN
   SIGNAL SQLSTATE '45000'
   SET message_text = "Password must have uppercase, lowercase letter and a digit;
END IF;
END;

Аналогично можете да направите същия по съдържание тригер с условие BEFORE UPDATE. Регулярните изрази може да ги използвате и в съхранени процедури и в обикновени SELECT заявки.

Писането на регулярни изрази в MySQL си има своите специфики и най-вече ограничения спрямо регулярните изрази в езиците за програмиране. Няма да се спираме на подробности, но при интерес може да ги намерите в документацията.

 



Добави коментар

Адресът на електронната поща няма да се публикува


*