Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Новости сайта "Упражнения по SQL" (http://www.sql-ex.ru) 217


Новости сайта "Упражнения по SQL (http://www.sql-ex.ru)"

Выпуск 217 от 22 ноября 2008 г.

Новым посетителям сайта

SQL Exercises Сайт посвящен изучению языка, с помощью которого осуществляется взаимодействие с реляционными (и не только) СУБД. Суть обучения состоит в выполнении заданий на написание запросов к учебным базам данных; при этом система контролирует правильность выполнения заданий. В настоящее время реализованы все операторы подъязыка манипуляции данными (DML), которые включают в себя оператор извлечения данных SELECT, а также операторы модификации данных - INSERT, DELETE и UPDATE.

Мы надеемся, что справочного материала сайта окажется достаточно для самостоятельного обучения. Кроме того, свои решения вы можете обсудить на форуме сайта. Опытных же специалистов приглашаем проверить (продемонстрировать) свое мастерство и принять участие в соревновании, обеспечиваемом рейтинговой системой учета времени выполнения заданий. Фактически, рейтинг ведется на втором этапе тестирования, который начинается сейчас после решения 50-й задачи первого этапа. При подсчете рейтинга каждого участника отбрасывается один самый худший показатель среди всех решенных им упражнений.

Демонстрация плана выполнения запроса и сравнительная оценка эффективности решений поможет вам освоить принципы оптимизации запросов, которые пригодятся на третьем рейтинговом этапе, который начинается после 138 задачи.

Имеется возможность получить сертификат по SQL DML при выполнении определенного количества заданий.


Новости сайта

§ Оценка стоимости запроса в рейтинге по эффективности, как заметил arcan, отличалась от оценки, которая дается на странице с упражнениями при повторном решении задачи. Привел в соответствие.

§ По просьбе Ozzy продублировал полную формулировку задачи в нижней части страницы форума.

§ Произошла замена задачи и изменение сертификационных требований:
- перенесена на обучающий этап задача 51;
- старая задача 69 теперь имеет номер 51 (сложность ее понижена до 1 балла);
- под номером 69 выставлена новая задача от нового автора anddros (сложность 2 балла);
- второй рейтинговый этап теперь начинается с задачи 51.
- просроченные заказы сертификатов удалены.

§ Одна задача (без учета вновь добавленной) до третьего этапа осталась:
49. GreyC (задач 136, время 26.792)

§ Изменения среди лидеров (решенные за неделю задачи третьего этапа):
11. Ozzy (144, 145)
18. Gavrila (145)
32. Umrikhina (141)

§ Продвинулись в рейтинге:
59. Eka (134, 20.554)
62. denzel (134, 212.085)

§ Продвижение ближайших претендентов на попадание в ТОР 100:
140. Romul_T (119, 42.205)
161. noname (111, 9.715)
176. Nariman Kurbanoff (112, 66.623)
182. breezemaster1 (110, 25.196)
191. enull (109, 23.340)
218. Vasilko (116, 6.698)

§ На этой неделе сертифицированы:
Pavel_yu (B08008576) [AR] - г.Сергиев Посад, Россия
GreyC (B08027996) [AR] - пос. Старый городок, МО, Россия
Инженер (A08037703) [BK] - г.Новокузнецк, Россия

§ Число подписчиков - 3813

Число участников рейтинга - 19526

Число участников второго этапа - 1609

Число участников третьего этапа - 42

Сертифицировано на сайте - 340

Лучшие результаты (ТОР 20)

No Person Number of
Sel_ex
Last_Sel Number of
DML_ex
Scores Days Days_2 Days_3 S_3 LastSolved LastVisit
1 Никотин В.М. (@Nikotin) 149 150 21 361 74 7.665 3.751 40 09 Nov 2008 21 Nov 2008
2 Сальников С.А. ($erges) 149 150 21 361 259 3.320 3.824 40 11 Nov 2008 21 Nov 2008
3 Печатнов В.В. (pvv) 148 149 21 357 357 30.865 17.490 36 10 Oct 2008 21 Nov 2008
4 Селезнёв А.С. (Артём С.) 147 149 21 354 322 38.520 29.235 36 25 Sep 2008 21 Nov 2008
5 Креславский О.М. (Arcan) 148 149 21 357 617 48.147 36.296 36 08 Oct 2008 21 Nov 2008
6 Карасёва Н.В. (vlksm) 148 149 21 357 866 77.240 49.173 36 18 Sep 2008 21 Nov 2008
7 Держальцев В.А. (MadVet) 139 146 21 338 1257 60.815 28.482 28 24 Sep 2008 06 Oct 2008
8 Любченко В.А. (IAS56) 138 146 21 337 615 403.439 373.617 28 11 May 2008 21 Nov 2008
9 Мурашкин И.В. (lepton) 143 148 21 343 950 43.615 33.116 26 28 Oct 2008 10 Nov 2008
10 Голубин Р.С. (Roman S. Golubin) 142 145 21 340 1122 93.054 58.822 25 13 Sep 2008 21 Nov 2008
11 Зотов П.Г. (Ozzy) 142 145 21 342 255 52.963 70.561 25 20 Nov 2008 21 Nov 2008
12 Nikolaenko A.V. (Shadow77) 144 147 21 344 436 77.520 14.010 23 22 Oct 2008 24 Oct 2008
13 Солдатенков Ю.С. (SolYUtor) 140 146 21 336 819 22.703 6.102 20 14 Aug 2008 23 Oct 2008
14 Белогурова К. (Katy_Ekb) 134 143 21 325 361 10.714 4.673 18 20 May 2008 16 Oct 2008
15 Егоров А.Б. (ABEgorov) 139 144 21 334 180 12.917 8.815 18 03 Aug 2008 12 Aug 2008
16 Войнов П.Е. (pаparome) 141 146 21 335 1125 3.132 .213 17 22 Sep 2008 07 Oct 2008
17 Дроздков А.Н. (anddros) 142 145 21 338 140 4.236 .921 17 14 Oct 2008 21 Nov 2008
18 Тарасов Д.Б. (Gavrila) 142 145 21 338 1181 26.191 3.677 17 19 Nov 2008 21 Nov 2008
19 iglbeat (iglbeat) 139 145 21 333 360 34.601 15.225 17 08 Aug 2008 25 Aug 2008
20 Северюхин Ю.А. (Venser) 130 142 21 316 335 4.925 .655 14 01 Feb 2008 04 Feb 2008

Лучшие результаты за неделю

No surname n_sel sel_all sel_scores dml_scores scores rating last_visit
1 Степаненко Н.С. (Micola) 25 38 58 17 75 1371 21 Nov 2008
2 >Жбанков В.Н. (Zhbankov) 30 30 57 17 74 2264 21 Nov 2008
3 >Мартынов (mart) 33 33 58 12 70 2516 21 Nov 2008
4 Бардаков В.Б. (Merdoc) 34 36 66 1 67 2939 18 Nov 2008
5 Gnusarev V.V. (xmix) 27 39 63 0 63 2467 21 Nov 2008
6 >Кашпирский А.Н. (КАН) 32 32 58 0 58 3781 21 Nov 2008
7 >Киреев А.А. (Kireev) 23 33 50 6 56 2768 21 Nov 2008
8 >Z A. (Andrey.ca) 30 30 56 0 56 3953 21 Nov 2008
9 >Зимин Н. (NZeemin) 29 29 54 0 54 4163 21 Nov 2008
10 >Славутинский В.В. (Vasilko) 20 116 50 0 50 218 21 Nov 2008
11 >Korotenko N. (nkoroten) 16 70 34 15 49 675 21 Nov 2008
12 >Прищепа Г.М. (Nucl3R) 22 35 48 0 48 3230 21 Nov 2008
13 >Шакиров О. (xm?!_(mo3roBa9_akTuBHocTb) 27 27 47 1 48 4821 21 Nov 2008
14 Песков В.С. (PADlabs.Corp) 22 33 47 0 47 3730 16 Nov 2008
15 Казаков С.Ю. (Ser-ga) 17 31 41 0 41 1808 20 Nov 2008
16 >Martynets (laline) 17 29 41 0 41 4178 21 Nov 2008
17 >Корзунин С.С. (Tarron) 18 70 36 0 36 506 21 Nov 2008
18 >Zheleznyak V. (Mr.Vik) 16 26 36 0 36 4930 21 Nov 2008
19 >Шиндин А.В. (AlShin) 14 108 34 0 34 196 21 Nov 2008
20 >платон Т. (упырь) 10 54 17 17 34 1196 21 Nov 2008
21 >Азбель Е. (enull) 13 109 33 0 33 191 21 Nov 2008
22 >Фоминых Ю.А. (yfominyh) 14 41 28 3 31 2271 21 Nov 2008
23 Гаврилин С.А. (bugagavr) 13 21 28 3 31 5806 19 Nov 2008
24 Яшин Д.С. (dzin) 13 34 30 0 30 3435 21 Nov 2008

Изучаем SQL

Массивы и списки в SQL Server 2005

Erland Sommarskog (оригинал: Arrays and Lists in SQL Server 2005 )
Перевод: Моисеенко С.И.

Введение

На общественных форумах, посвященных SQL Server, часто приходится слышать такой вопрос: "Как мне использовать множества в SQL Server"? Или почему не работает SELECT * FROM tbl WHERE col IN (@list)? Короткий ответ на первый вопрос гласит, что SQL Server не имеет множеств - SQL Server имеет таблицы. Однако Вы не можете передать с клиента таблицу на вход SQL Server. То, что Вы можете сделать - это задать строку и распаковать ее в таблицу.

Эта статья описывает множество различных способов сделать это, как хороших, так и плохих. Сначала я сформулирую проблему (включая быстрое, если не лучшее, решение). Затем последует краткий обзор методов, после чего обсуждаются общие проблемы, независимо от того какой метод Вы используете. Покончив с вводной частью, в остальной части статьи я детально опишу все методы, обсуждая при этом их сильные и слабые стороны. Чтобы выяснить, насколько хорошо работают эти методы, я провел тесты производительности и поместил результаты этих тестов в отдельном приложении.

Если Вас пугает чрезмерный объем этой статьи, Вам следует знать, что ее не обязательно читать последовательно, переходите по ссылкам, куда вам нравится. Если Вы простой программист SQL, кто хочет узнать, "как это сделать?", то можете бросить чтение уже после первого решения, если спешите. Если у Вас есть немного больше времени, Вы читаете введение в проблему, краткий обзор и раздел "Общие соображения"; изучаете методы, которые кажутся вам наиболее предпочтительными. Истинные любители SQL, которые интересуются оценками производительности, сочли бы объяснения методов немного утомительными и могут просмотреть по диагонали эти разделы, перейдя непосредственно к тестам производительности в приложении.

Замечу, что эта статья относится только к SQL Server 2005 (осталось лишь несколько обратных ссылок на SQL 2000). Если Вы используете SQL 2000, есть более ранняя версия этой статьи, которая относится к SQL 2000, SQL 7 и SQL 6.5.

Все примеры в этой статье относятся к базе данных Northwind. Эта база данных не поставляется с SQL Server 2005, но Вы можете скачать ее установочный скрипт с вебсайта Microsoft.

Введение в проблему

Список значений, разделенных запятыми

Вы имеете множество значений ключа, идентифицирующих несколько строк в таблице, которые требуется получить. Если Вы используете операторы SQL в коде клиента, то могли бы написать что-то похожее на следующий фрагмент:

   SQL = "SELECT ProductID, ProductName FROM Northwind..Products " & _
         "WHERE ProductID IN (" & List & ")"
   rs = cmd.Execute(SQL)

Здесь LIST - переменная, которой Вы где-нибудь присвоили строковое значение, представляющего собой список, разделенный запятыми, например: "9, 12, 27, 39".

Такой код - плохой прием, поскольку никогда не следует встраивать значения параметров в строку запроса. (Объяснение этого выходит за рамки данной статьи, но я обсуждаю это подробно в моей статье The Curse and Blessings of Dynamic SQL ("Проклятие и благословения динамического SQL") , в частности, в разделах SQL Injection (инъекция SQL) и Caching Query Plans ("Кэширование плана запроса").

Поскольку это плохой метод, Вы захотите использовать хранимые процедуры. Однако, как кажется на первый взгляд, нет никакого очевидного способа сделать это. Многие пробовали так:

CREATE PROCEDURE get_product_names @ids varchar(50) AS
SELECT ProductID, ProductName
FROM   Northwind..Products
WHERE  ProductID IN (@ids)

Однако при тестировании:

EXEC get_product_names '9, 12, 27, 37'

возникала ошибка:

Server: Msg 245, Level 16, State 1, Procedure get_product_names, Line 2
Syntax error converting the varchar value '9, 12, 27, 37' to a column of data type int.
(Ошибка синтаксиса, преобразование значения varchar - '9, 12, 27, 37' к столбцу с типом данных int)

Причина неудачи состоит в том, что мы уже не используем динамический SQL, и @ids - это только одно значение в предложении IN. Предложение IN можно было бы прочитать так:

... WHERE col IN (@a, @b, @c)

Чтобы внести еще больше ясности, предлагаю вам посмотреть этот небольшой скрипт:

CREATE TABLE #csv (a varchar(20) NOT NULL)
go
INSERT #csv (a) VALUES ('9, 12, 27, 37')
INSERT #csv (a) VALUES ('something else')
SELECT a FROM #csv WHERE a IN ('9, 12, 27, 37')

Правильный способ разрешить ситуацию состоит в том, чтобы использовать функцию, которая распакует строку в таблицу. Ниже самая простая из таких функций:

CREATE FUNCTION iter$simple_intlist_to_tbl (@list nvarchar(MAX))
   RETURNS @tbl TABLE (number int NOT NULL) AS
BEGIN
   DECLARE @pos        int,
           @nextpos    int,
           @valuelen   int

   SELECT @pos = 0, @nextpos = 1

   WHILE @nextpos > 0
   BEGIN
      SELECT @nextpos = charindex(',', @list, @pos + 1)
      SELECT @valuelen = CASE WHEN @nextpos > 0
                              THEN @nextpos
                              ELSE len(@list) + 1
                         END - @pos - 1
      INSERT @tbl (number)
         VALUES (convert(int, substring(@list, @pos + 1, @valuelen)))
      SELECT @pos = @nextpos
   END
  RETURN
END

Функция просто в итерационном процессе проходит строку, находя запятые, и извлекает значения одно за другим. Единственная сложность - логика обработки последнего значения в строке. Ниже пример использования этой функции:

пример использования этой функции:
CREATE PROCEDURE get_product_names_iter @ids varchar(50) AS
   SELECT P.ProductName, P.ProductID
   FROM   Northwind..Products P
   JOIN   iter$simple_intlist_to_tbl(@ids) i ON P.ProductID = i.number
go
EXEC get_product_names_iter '9, 12, 27, 37'

Итак, мы имеем решение проблемы. Но позвольте мне сказать прямо, что эта функция не слишком быстрая, и почти все методы, которые я буду обсуждать в этой статье, быстрее данного. Тем не менее, этого достаточно для многих ситуаций, особенно если список короткий. Поэтому если Вы торопитесь заняться вашим проектом, можете остановиться на этом и вернуться позже, если Вам будет любопытно или Вы столкнетесь с проблемами производительности, чтобы изучить другие варианты.

Если у Вас списки уже находятся в столбце таблицы, и Вы торопитесь, перейдите к разделу Unpacking Lists in a Table ("Распаковка списков в таблицу").

(Продолжение следует...)

Полезная информация

§ Приглашаем вас посетить новый проект - Интерактивный учебник по SQL.
   Ресурс позиционируется как "справочное обеспечение" для сайта SQL-EX.RU, но может использоваться и независимо от него.

§ Онлайновый выпуск рассылки можно почитать на сайте.

§ Все статьи, публикуемые в рассылке, затем выкладываются на сайте Книги и статьи по SQL.

§ Хотите поддержать проект? Вот инструкция по применению. :-)

Контакты

По всем вопросам, связанным с функционированием сайта, проблемами при решении упражнений, идеями вы можете обращаться к Сергею И.Моисеенко msi77[@]yandex.ru. Вы также можете предложить свои задачи для публикации на сайте.

Подписка Subscribe.Ru
Новости сайта "Упражнения по SQL"

В избранное