Всем привет. Мы уже научились создавать таблицы и в этом видео мы будем помещать в них данные и извлекать их обратно. Есть термин CRUD - это сокращение от английских слов create, read, update и delete, создавать, читать, обновлять и удалять. Это - акроним, обозначающий четыре базовых функции, используемых при работе с хранилищами данных. В MySQL CRUD реализуется с помощью четырех видов запросов: создание - insert, чтение - select, редактирование - update и удаление - это запрос delete. Начнём мы с вставки новых данных с помощью insert. Синтаксис insert базовый INSERT [IGNORE] [INTO] table, имена колонок, которые вставляем, и значение для этих колонок, причем можно несколько списков значений, тогда можно вставить за один insert несколько рядов. Также дополнительно можно указать [ON DUPLICATE KEY UPDATE] , и что делать в случае конфликтов. Значит, значение для каждой колонки представляется либо выражением каким-то, это может быть число, строка, какие-то формулы или словом default, что означает вставить значение колонки, которое прописано в ней по умолчанию. Также существует другой синтаксис INSERT [IGNORE] [INTO] , имя таблицы, но не перечисляются отдельно колонки и потом отдельно списки значений для этих колонок, а пишется SET, и дальше колонка равно значение, колонка равно значение. Ну и точно так же [ON DUPLICATE KEY UPDATE] в конце можно добавить. Существует также третий вид INSERT, когда данные в таблицу вставляются на основе данных, выбранных из другой таблицы или таблиц. Синтаксис этого INSERT [IGNORE] [INTO] table, имена колонок, которые мы будем вставлять, и дальше идет SELECT, какой-то SELECT, выбирающий данные из другой таблицы или из других таблиц. Также можно в этом SELECTе указывать какие-то формулы и константы, в принципе. В общем, на основе вот этих всех данных совмещенных можно заполнить новую таблицу. Также у INSERTа есть еще опция, которую я не упомянул. Я упомянул INSERT [IGNORE] , это - одна из опций, ее можно указывать, можно не указывать. Есть опция low priority, high priority, delete. Но, на самом деле, low priority и high priority определяют порядок, в котором будут вставляться данные относительно запроса в SELECT. В общем, достаточно, на самом деле, много нюансов, но ни low priority, ни high priority не работают в таблицах InnoDB. А мы рассматриваем именно движок InnoDB как основной, и поэтому не имеет смысла, а delete вообще в последних версиях MySQL игнорируется. Поэтому как бы формально в INSERTе они присутствуют, но мы их даже не будем рассматривать, потому что они нам не пригодятся. INSERT вставляет новые ряды в таблицу. Как я сказал выше уже, INSERT values и INSERT SET вставляет на основе каких-то конкретных данных, которые вы указываете. А INSERT SELECT - на основе данных из других таблиц. Если указать в конце, я уже упоминал, [ON DUPLICATE KEY UPDATE] , то можно обновить данные в рядах, которые при попытке вставить данные, вызвали конфликты дублирующих со значением. Вы знаете, если у вас есть первичный ключ или уникальный ключ какой-то, и вы оставляете новые данные с таким же ключом, то будет конфликт данных, и ряд этот невозможно вставить, поскольку будут нарушены ограничения целостности. Вот в этом случае можно этот ряд не вставить, а найти этот дублирующийся ряд исходный и обновить его какими-то значениями, или же, как мы посмотрим дальше, IGNORE как раз означает проигнорировать такой INSERT, то есть просто не вставлять ряд. А если без того и другого, то будет ошибка. Итак, IGNORE игнорирует ошибки в случае конфликтов каких-то с дублирующимися данными. На самом деле, не только их. Если какие-то вы вставляете значения, не подходящие по типам, то эти значения тоже могут быть как-то проигнорированы или приведены к значениям по умолчанию. В общем, IGNORE найдет любые ошибки при INSERTе. Также есть вариант сделать вместо INSERTа REPLACE, по синтаксису он очень похож на INSERT, но, как можно понять из его названия, он не только вставляет данные, но и заменяет их, то есть в случае конфликтов, там, где INSERT бы отвалился с ошибкой как раз, REPLACE заменяет эту строку на новые данные, старые данные на новые. Он очень похож в данном смысле на INSERT [ON DUPLICATE KEY UPDATE] как раз, который тоже заменяет, но в отличие от UPDATE, который действительно обновляет данные в случае конфликтов, REPLACE, на самом деле, внутри себя в случае конфликта удаляет старую строку и потом вставляет новую. А это чревато, в свою очередь, вещами, такими неприятными как, вы помните про ограничения, что одна таблица может ссылаться на другую, и в случае удаления данных из исходной таблицы удаляются все связанные данные из другой таблицы. Так вот если вы сделаете INSERT [ON DUPLICATE KEY UPDATE] и обновите данные, все будет хорошо, но если вы сделаете REPLACE, да, данное в исходной таблице обновятся, но данные в связанной таблице при этом удалятся, потому что сначала строка будет удалена, данные связанной таблицы удалятся, потом будет вставлена новая строка, но данные в связанной таблице уже не появятся. Также когда вы вставляете данные, вы можете не указывать какие-то колонки, и, например, если в настройках таблицы колонка указана как авто инкремент, ей автоматически будет присвоен следующий номер. Автоматически будет проставлено значение больше чем самое последнее в предыдущих рядах, и этот номер, который автоматически SQL присвоит, можно узнать с помощью встроенной функции LAST_INSERT_ID, то есть, вы вставляете строчку, а потом вам надо понять, какой же ID получился, его можно тоже получить. Дальше перейдем к чтению данных с помощью SELECT. Общий синтаксис такой: SELECT, можно указать слово [DISTINCT] , можно указать опцию [SQL_CALC_FOUND_ROWS] , дальше идут выражения, которые мы выбираем, как правило, это имена колонок, FROM, дальше список таблиц, но там есть еще и другие условия соединения таблиц и так далее,. то есть, FROM - таблица или таблицы, WHERE - условия выбора, ORDER BY - условия сортировки, LIMIT - это ограничение, то есть можно выбрать не все ряды, которые подпадают под условия, а только часть их, уменьшить выборку, и дополнительные ключевые слова [FOR UPDATE I LOCK IN SHARE MODE]. Давайте рассмотрим подробнее. На самом деле, я выкинул еще часть параметров, которые есть в SQL. Какие-то из них мы в следующих видео, какие-то, опять-таки, либо очень специфичные, либо могут нам вообще никогда не потребоваться, поэтому я их тоже опустил. Например, есть SQL small result, SQL big result, SQL buffer result, которые отвечают за то, как результат выборки будет обработан, есть группировки, having, join, их мы рассмотрим дальше. Еще раз, select-expr, который в selecte указывает, какую колонку нужно извлечь. И должно быть в селекте хотя бы одну, то есть селектом нужно извлечь хотя бы одну колонку, не может быть select вообще без указания колонок. Также можно извлекать колонку не под своим именем, т.е. автоматически при извлечении присваивать ей alias, например, вы можете извлечь name и переименовать ее и при этом в user name, то есть у вас в запросе на самом деле колонка name будет фигурировать под именем user name. И также можно написать select*, это значит выбрать вообще все колонки из таблицы. Table_references указывает, из какой таблицы или таблиц нужно извлекать ряды данных, и таблицы, точно также им можно присваивать алиасы в этом селекте,. то есть переименовывать, например у вас таблица имеет длинное название, вы не хотите его везде повторять дальше в условиях, в выборе и вы можете назвать ее, например, просто А, будет гораздо короче и удобнее. Если у вас нет условия WHERE, то извлекаются все ряды из таблицы, вообще все. Если же условие есть, то там присутствует where condition, это какое-то выражение, использующее внутри себя колонки, какие-то вычисления опять таки, и если результатом этого выражения для какого-то ряда является TRUE, то этот ряд будет отобран в результирующую выборку, если нет, то этот ряд будет проигнорирован. Дальше, ORDER BY позволяет сортировать ряды по какой-то колонке или колонкам, а также по их алиасам, можно даже по порядковому номеру колонки или по каким-то выражениям, то есть не просто по значению колонки, а какому-то выражению колонки. Сортировать можно как по возрастанию, то есть от меньшего к большему, так и по убыванию - от большего к меньшему. С помощью лимита, как я говорил, можно получить только часть выборки, то есть, например, можно написать LIMIT 10, и если бы у вас так выбралось, сто рядов каких-то под условия попало, то выберутся только первые 10. А также можно указать два числа, то есть десять - это с первого по десятый выбирается, а можно как два числа, с какого и сколько, то есть, например, можно выбрать не первые 10, а начиная с пятого, и от него 10 рядов. Вот так. Также DISTINCT я упоминал, это позволяет выкинуть одинаковые ряды из запроса, то есть, например, у вас есть таблица пользователей, у них есть разные поля, и, допустим, у них есть имя. И у многих пользователей имя совпадает. В общем-то имен не так много, а пользователей много разных. И вы хотите просто узнать, какие же вообще имена пользователей у вас бывают в таблице. Вот вы делаете SELECT name из таблицы, и тогда вы получите список всех имен, в том числе будут дубли. Если вы напишите SELECT DISTINCT name, то, очевидно, вы получите только различные имена. SQL_CALC_FOUND_ROWS - такая опция, она позволяет посчитать, сколько рядов отобрала выборка, не учитывая лимит. То есть, у вас выборка выбрала 100 рядов, но вы в конце написали лимит и получили в итоге 10 рядов. Но выбрали то вы 100 изначально. Чтобы узнать, сколько же рядов было изначально, до лимита, помогает SQL_CALC_FOUND_ROWS. Это удобно, если вы делаете, например, паджинацию, вам надо понять, сколько всего у вас страниц, а количество страниц зависит от того, сколько всего записей есть. Но при этом на каждой конкретной странице вы выводите какую-то порцию записей. Там нужны лимит как раз и CALC_FOUND_ROWS. Опция FOR UPDATE позволяет заблокировать на чтение и запись все ряды, которые были просмотрены при селекте, кстати, просмотрены именно, а не выбраны. Как раз помните, мы разговаривали с вами про транзакции, про режимы блокировок, про уровни изоляции. Вот это относится к этому. То есть, вы можете какие-то ряды отобрать и сразу заблокировать, чтобы кто-то другой не начал их изменять. Говоря SELECT FOR UPDATE, вы говорите как бы MySQL, что вы отобрали какие-то данные, и вы хотите их изменить и записать обратно. И в этот момент между вашим чтением и последующей записью никто не должен их изменить. Также есть LOG AND SHARE MODE, который блокирует какие-то записи просмотренные от записей удаления, но разрешает другим транзакциям читать эти данные. На самом деле я немножко упрощаю, всё слегка сложнее, потому что зависит от режимов изоляции и так далее. Но смысл именно такой. Давайте рассмотрим какой-то очень простенький пример селекта, потому что я много рассказал. Допустим, у нас есть какая-то таблица, скажем, пользователей, в ней есть id, может быть, какие-то имена, есть логин. Допустим, первые пять пользователей у нас тестовые. Мы знаем, что это тестовые пользователи, они у нас не должны участвовать в выборке, поэтому мы выбираем, мы пишем WHERE 'id'>5, тех пользователей, у которых id больше 5, кроме первых. И мы хотим, например, выбрать пользователей, у которых возраст 10, 20 или 30 лет. Для этого мы пишем 'age' IN и перечисляем таких вот. И хотим выбрать их id и длину их логина, не знаю, мы хотим, может быть, какую-то аналитическую работу провести и только над этими пользователями. Смотрите, мы можем выбрать как название колонки, как колонку id, можем выбрать какую-то функцию от какой-то колонки LENGTH ('login'), то есть длину логина, и переименовать ее при этом, назвать просто словом length. То есть у нас в выборке будет length, и оно будет равно длине логина для каждого ряда. Мы можем даже выбирать просто константу, вот я выбрал единицу, то есть в каждом ряду в этом месте будет единица, и назвать ее raid. Также мы можем упорядочить эти данные по имени. Заметьте при этом само имя у нас в селекте не присутствует, то есть мы не выбираем его, но тем не менее данные будут отсортированы в том порядке, в котором шли их имена, и ограничить эту выборку первыми десятью пользователями. Такой запрос нам позволит это все сделать. Дальше поговорим про UPDATE. UPDATE, на самом деле, по синтаксису похож на что-то среднее между INSERT и SELECT. На самом деле, поскольку он примерно это же и делает, он отбирает какие-то записи, как это делает SELECT, и обновляет в них данные. Соответственно в UPDATE можно также указать IGNORE, игнорировать ошибки, таблица или таблицы, которые надо обновлять, и дальше SET column name, то есть устанавливаем какие-то значения для колонок, причем значения могут быть тоже какими-то формулами, то есть мы можем устанавливать значения как какие-то числа, строки и так далее, так и в какие-то функции от результатов от других колонок, от этой же колонки, можно, например, увеличить какое-то поле, написать col_name=col_name +1, например, что-то в этом духе. Соответственно, есть условие, по которому мы обновляем ряды. И если мы объявляем только одну таблицу, то ещё допускается ORDER BY и LIMIT. Если в UPDATE мы указываем несколько таблиц, это более сложно, там ORDER BY и LIMIT не допускаются. Также давайте рассмотрим удаление. Удаление опять-таки по синтаксису похоже на SELECT больше всего, потому что по сути оно отбирает какие-то ряды, но не возвращает нам их, а удаляет. У него тоже есть WHERE, можно ORDER BY, можно LIMIT, просто эти ряды будут удалены. Вот, собственно, и всё. Достаточно просто. Давайте подведем итоги. Итак, основные операции имеют аббревиатуру CRUD - create, read, update и delete. В MySQL для этого используются INSERT, SELECT, UPDATE и DELETE. Мы рассмотрели упрощенный синтаксис SQL для всех этих действий. В следующем видео мы усложним синтаксис SELECT, добавим выборки из нескольких таблиц, группировки данных, подсчет агрегатных функций и немножко попрактикуемся в выполнении конкретных селектов на конкретных таблицах.