В SQL курсорите служат като указател, който позволява на езика за приложно програмиране да се справя с резултатите от заявката един ред по ред. Тази статия бързо изследва концепцията зад и показва как да декларирате курсори, да отваряте, извличате данни от тях и след това да ги затваряте.
SQL курсори
Данните в релационната база данни се управляват под формата на набори. В резултат на това резултатите от заявката, връщани от SQL оператори SELECT, се наричат резултатни набори. Резултатите не са нищо друго освен комбинации от един или повече редове и колони, извлечени от една или повече таблици. Можете да превъртите през наборите от резултати, за да извлечете необходимата информация. Върнатите елементи от данни се използват от езици за програмиране като Java или други за специфични цели на приложението. Но тук се крие проблемът с несъответствието на импеданса поради разликата в конструкцията между модела на базата данни и модела на езика за програмиране.
Моделът на SQL база данни има три основни конструкции:
- колони (или атрибути) и техните типове данни
- редове (записи или кортежи)
- таблици (колекция от записи)
Следователно основното несъответствие между два модела е:
- Атрибутните типове данни, налични в модела на база данни, не са същите като типовете променливи, използвани в езиците за програмиране. Има много хост езици и всеки има различен тип данни. Например, типовете данни на C/C++ и Java са различни, както и типовете данни на SQL. Следователно е необходим обвързващ механизъм за смекчаване на проблема с несъвместимостта.
- Резултатът, върнат от SQL операторите SELECT, са множество набори от записи, където всеки запис е колекция от атрибути. Езиците за програмиране на хост обикновено работят върху индивидуални стойности на данни на кортеж, върнати от заявката. Ето защо е от съществено значение резултатите от SQL заявката да се съпоставят със структурата на данните, поддържана от езика за програмиране. Механизмът на цикъл върху кортежи е необходим за повторение на кортежи и техните стойности на атрибути.
Курсорът действа като променлива на итератор, за да преглежда кортежи, върнати от SQL заявката, и да извлича отделни стойности във всеки кортеж, които след това могат да бъдат съпоставени с подходящ тип програмни променливи.
Следователно курсорът служи като указател, който позволява на програмния език да обработва резултата от заявката един запис в даден момент. Курсорът може да преминава през всички редове на резултата от заявката, като се фокусира върху един ред в даден момент. Помислете за следната SQL заявка:
SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date) = MONTH(CURRENT_DATE) AND DAY(birth_date) = DAY(CURRENT_DATE);
Резултатът от заявката от горното изявление връща данни за служителите на всички онези служители, чиято рождена дата пада на текущия ден от конкретен месец. Резултатът може да съдържа много редове, но езикът на приложението на хоста може да работи с един ред в даден момент. В резултат на това курсорът се декларира като вграден SQL израз в езика за програмиране на приложения. След това курсорът се отваря подобно на файл и се извлича един ред от резултата от заявката. Други редове се извличат последователно, докато курсорът се затвори.
Деклариране на курсор
Курсорите се декларират подобно на променлива. Дава се име, има изрази за отваряне на курсора, извличане на резултата от заявката и накрая затваряне на курсора. Имайте предвид, че различните реализации на SQL поддържат използването на курсори по различен начин. Но има общо съгласие за това как трябва да бъде написан курсорът.
Трябва да използваме SQL изрази, за да приложим напълно функционалността на курсора, защото простото деклариране на курсор не е достатъчно за извличане на данни от SQL база данни. Има четири основни стъпки за деклариране на курсор:
ДЕКЛАРИРАНЕ НА КУРСОР: Декларацията започва с даване на име на курсора и присвояване на израза на заявката, който да се извиква при отваряне на курсора.
ОТВОРЕНО: Операторът open изпълнява присвоения израз на заявка и прави готов резултат от заявката за последващо FETCH.
ИЗВЛЕЧВАНЕ: Извлича стойности на данни в променливи, които след това могат да бъдат предадени на хост програмен език или към други вградени SQL изрази.
ЗАТВОРИ: Курсорът е затворен от извличане на други резултати от заявка.
Синтаксисът е следният:
DECLARE <cursor_name> [SENSITIVE | INSENSITIVE | ASENSITIVE] [SCROLL | NO SCROLL] CURSOR [ WITH HOLD | WITHOUT HOLD] [ WITH RETURN | WITHOUT RETURN] FOR <sql_query_expression> [ ORDER BY <sort_expression>] [ FOR {READ ONLY | UPDATE [ OF <list_of_column>]}]
Съществената част от декларацията на курсора е както следва:
DECLARE <cursor_name> FOR <sql_query_expression>
Незадължителната част, като [SENSITIVE | НЕЧУВСТВИТЕЛЕН | ASENSITIVE] означава дали курсорът е чувствителен към промените и дали да ги отрази в резултата от заявката. ЧУВСТВИТЕЛНО означава, че курсорът е засегнат от промени, НЕЧУВСТВИТЕЛНО означава, че курсорът не е засегнат, а ЧУВСТВИТЕЛНО означава, че промените могат или не могат да бъдат видими за курсора. Ако не е посочено, приема опция ASENSITIVE.
Незадължителният [SCROLL | NOSCROLL] дефинира способността за превъртане на курсора. Ако не е посочено, приема опцията NO SCROLL.
Незадължителният [ WITH HOLD | WITHOUT HOLD] определя дали да се задържи или да се затвори автоматично, когато транзакцията, дължаща се на курсора, бъде завършена. Ако не е посочено, поддържа опцията БЕЗ ЗАДЪРЖАНЕ.
Незадължителният [ С ВРЪЩАНЕ | WITHOUT RETURN] определя дали да върне резултатния набор от курсора на извикващия, като друга SQL рутина или хост език. Ако не е посочено, това означава БЕЗ ВРЪЩАНЕ.
Клаузата ORDER BY се използва за сортиране на резултата от заявката, върнат според определената техника за сортиране.
Опцията UPDATE се отнася до използването на оператор UPDATE или DELETE е асоцииране с редовете, върнати от оператора SELECT на курсора. Всяка такава модификация не е възможна, ако посочим опция САМО ЧЕТЕНЕ. Ако не е посочено, тогава по подразбиране се приема опцията UPDATE.
Следователно обикновен курсор може да бъде деклариран, както следва:
DECLARE mycursor CURSOR FOR SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date) = MONTH(CURRENT_DATE) AND DAY(birth_date) = DAY(CURRENT_DATE);
Курсорите в MySQL
Обикновено има два типа курсори, открити в MySQL:курсори само за четене и курсори само за напред. Тези курсори могат да се използват за съхранена процедура в MySQL. Тези курсори ни помагат да преглеждаме резултатите от заявката един ред наведнъж и да извличаме променливи за по-нататъшна обработка. Възможно е да декларирате повече от един курсор и да ги вложите в цикли. Обърнете внимание, че курсорите са само за четене, защото се използват за итерация върху временни таблици. Курсорът обикновено изпълнява заявката, докато я отваряме.
Един от проблемите с курсора в MySQL е, че те могат да забавят изпълнението на заявката поради допълнителни I/O операции, които извършват. Това важи особено за истински големи типове данни като BLOB и TEXT. Тъй като курсорите работят с временни таблици, тези типове не се поддържат в таблици в паметта. Следователно, докато работи с тези типове, MySQL трябва да създава временни таблици на диска и това изисква много I/O операции и това също в бавни устройства като дискове. Това е основната причина за бавното представяне на курсора.
MySQL също не поддържа курсори от страна на клиента, но клиентският API може да ги емулира, ако е необходимо. Но тогава това не е много по-различно от извличането на резултата в масив на език за програмиране като Java и вместо това да ги манипулирате там.
Ето пример за това как да пишете курсори в MySQL.
CREATE PROCEDURE 'cursor_demo'() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE id INT(11); DECLARE fn varchar(14); DECLARE ln varchar(16); DECLARE bdate date; DECLARE mycursor CURSOR FOR SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date)=MONTH(CURRENT_DATE) AND DAY(birth_date)=DAY(CURRENT_DATE); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN mycursor; fetch_loop: LOOP FETCH mycursor INTO id, fn, ln, bdate; IF done THEN LEAVE fetch_loop; END IF; SELECT id, fn, ln, bdate; END LOOP; CLOSE mycursor; END
Извикайте съхранената процедура, както следва:
mysql> CALL cursor_demo
Процедурата извлича редовете от таблица с име служител чиято рождена дата съвпада с текущия ден и месец в курсор с име mycursor и просто ги отпечатва с помощта на оператор SELECT.
Вижте MySQL Documentation на Cursor за повече информация.
Заключение
Курсорите не са нищо друго освен указатели към наборите от записи, върнати от SQL заявка. Показалецът обикновено сочи към един ред в даден момент и може да бъде обходен в цикъл за извличане на отделни записи. SQL обикновено се използва за директно извикване за достъп и създаване на обекти с данни. Курсорите осигуряват техниката на интерактивен SQL, където позволява ad hoc изпълнение на SQL изрази, улеснено чрез клиентско приложение. Механизмът на курсора използва модела за достъп до данни, при който SQL изразите са вградени в хост език като C, C++ или Java и т.н. Това е само поглед върху това, с което курсорът ще започне. Обърнете се към съответната документация на базата данни на SQL за подробности относно специфичните норми за различно изпълнение.
# # #