← Август 2008 → | ||||||
1
|
3
|
|||||
---|---|---|---|---|---|---|
4
|
5
|
6
|
7
|
8
|
10
|
|
11
|
12
|
13
|
14
|
15
|
17
|
|
18
|
19
|
20
|
21
|
22
|
24
|
|
25
|
26
|
27
|
28
|
29
|
31
|
За последние 60 дней ни разу не выходила
Сайт рассылки:
http://www.sql-ex.ru
Открыта:
15-09-2004
Статистика
0 за неделю
Новости сайта "Упражнения по SQL" (http://www.sql-ex.ru) 201
Новости сайта "Упражнения по SQL (http://www.sql-ex.ru)" Выпуск 201 (2 августа 2008 г.)Новым посетителям сайтаСайт посвящен изучению языка, с помощью которого осуществляется взаимодействие с реляционными (и не только) СУБД. Суть обучения состоит в выполнении заданий на написание запросов к учебным базам данных; при этом система контролирует правильность выполнения заданий. В настоящее время реализованы все операторы подъязыка манипуляции данными (DML), которые включают в себя оператор извлечения данных SELECT, а также операторы модификации данных - INSERT, DELETE и UPDATE.Мы надеемся, что справочного материала сайта окажется достаточно для самостоятельного обучения. Кроме того, свои решения вы можете обсудить на форуме сайта. Опытных же специалистов приглашаем проверить (продемонстрировать) свое мастерство и принять участие в соревновании, обеспечиваемом рейтинговой системой учета времени выполнения заданий. Фактически, рейтинг ведется на втором этапе тестирования, который начинается сейчас после решения 54-х задач первого этапа. При подсчете рейтинга каждого участника отбрасывается один самый худший показатель среди всех решенных им упражнений. Демонстрация плана выполнения запроса и сравнительная оценка эффективности решений поможет вам освоить принципы оптимизации запросов, которые пригодятся на третьем рейтинговом этапе, который начинается после 138 задачи.Имеется возможность получить сертификат по SQL DML при выполнении определенного количества заданий. Новости сайта§ Уточнили формулировки 52 и 89 (английский вариант - сообщения sulo), 72 (обучающий этап - сообщение s.pereira). § Автор - $erges - добавил проверочные данные для задачи 15 (Select). § Вняв пожеланию shimanskievgeni, улучшили юзабилити страниц с упражнениями. Теперь отправлять запрос на проверку можно клавиатурно (Ctrl+Enter). Табуляцию можно осуществить с помощью Ctrl+Shift+t. Последнее улучшит форматирование запроса при публикации на форуме, обновление которого тоже на подходе. § С результатом (задач 138, время 27.904) к третьему этапу подошел Ozzy. § Изменения среди лидеров (решенные за неделю задачи третьего этапа): § Новые лица в ТОР 100 и вернувшиеся туда: § Продвинулись в рейтинге: § Продвижение ближайших претендентов на попадание в ТОР 100: § На этой неделе сертифицированы: § Число подписчиков - 3798 Число участников рейтинга - 16538 Число участников второго этапа - 1470 Число участников третьего этапа - 34 Сертифицировано на сайте - 302 Лучшие результаты (ТОР 20)
Лучшие результаты за неделю
Изучаем SQLСтолбцы Identity (окончание, начало в вып.200)Nigel Rivett (оригинал: Identity Columns )Перевод Моисеенко С.И. Изменение текущего значения seedМы видели, что текущее значение seed может быть изменено вставкой, но только в направлении шага. Лучший способ сделать это - использовать команду DBCC checkident. Чтобы установить значение seed, используется ключевое слово reseed. CREATE TABLE #d (i INT IDENTITY (5,2), j INT) INSERT #d (j) SELECT 1 INSERT #d (j) SELECT 1 SELECT * FROM #d i j ----------- ----------- 5 1 7 1 DBCC checkident(#d) Checking identity information: current identity value '7', current column value '7'. (Проверка информации identity : текущая значение identity '7', текущее значение столбца '7'.) DBCC checkident(#d, reseed, 2) Checking identity information: current identity value '7', current column value '2'. (Проверка информации identity : текущая значение identity '7', текущее значение столбца '2'.) Отметьте для себя, что впервые текущее значение seed отличается от последнего установленного значения. INSERT #d (j) SELECT 2 SELECT * FROM #d i j ----------- ----------- 5 1 7 1 4 2 Мы можем также сбросить текущее значение seed к его исходному значению посредством "усечения" (команда Truncate) таблицы. Заметим, что простое удаление (DELETE) не делает этого. TRUNCATE TABLE #d DBCC checkident(#d) Checking identity information: current identity value 'NULL', current column value 'NULL'. (Проверка информации identity : текущая значение identity 'NULL', текущее значение столбца 'NULL'.) INSERT #d (j) SELECT 1 SELECT * FROM #d i j ----------- ----------- 5 1 DBCC checkident(#d) Checking identity information: current identity value '5', current column value '5'. (Проверка информации identity : текущая значение identity '5', текущее значение столбца '5'.) Как узнать значение IdentityТипичная задача - как узнать значение identity для вставленной строки. Есть несколько операторов, связанных с этим scope_identity ()Возвращает последнее значение idtntity, вставленное в текущем окружении и сессии. Это, как правило, единственная полезная функция. На него не влияют ни другие подключения или таблицы, ни триггеры. @@identityВозвращает последнее значение identity , вставленное в любых окружениях. Это означает, что если триггер вставляет в таблицу с identity, то это значение и будет возвращено. Это означает, что добавление триггеров репликации или аудита в базу данных может изменить значение @@identity. В более ранних версиях sql server это было единственным средством вернуть значение identity, и это всегда нужно было учитывать. ident_current ('таблица')Возвращает последнее значение, вставленное в эту таблицу на любом подключении. Не забудьте заключать название таблицы в кавычки. Как утверждалось ранее scope_identity () - вероятно единственная из всех этих функций, которую Вам придется использовать. Использование Scope_Identity ()Как утверждалось ранее scope_identity () возвращает последнее вставленное значение identity . CREATE TABLE #t1 (i INT IDENTITY(5,1), j INT) INSERT #t1 (j) SELECT 1 SELECT SCOPE_IDENTITY(), MAX(i) FROM #t1 --------------------------------------- ----------- 5 5 scope_identity также возвращает значение после отката BEGIN TRAN INSERT #t1 (j) SELECT 1 ROLLBACK TRAN SELECT SCOPE_IDENTITY(), MAX(i) FROM #t1 --------------------------------------- ----------- 6 5 но значение не обновляется при сбое в результате нарушения ограничений индекса, хотя значение устанавливается CREATE UNIQUE INDEX ix ON #t1 (j) INSERT #t1 (j) SELECT 1 SELECT SCOPE_IDENTITY(), MAX(i) FROM #t1 --------------------------------------- ----------- 6 5 INSERT #t1 (j) SELECT 2 SELECT SCOPE_IDENTITY(), MAX(i) FROM #t1 --------------------------------------- ----------- 8 8 Добавление столбца Identity в таблицуСтолбец identity может быть добавлен в таблицу с помощью оператора alter table. Значения будут присваиваться столбцу согласно seed и step. В этом случае SCOPE_IDENTITY () не будет возвращать установленное значение. CREATE TABLE #t2 (j INT) INSERT #t2 (j) SELECT 1 INSERT #t2 (j) SELECT 1 INSERT #t2 (j) SELECT 1 INSERT #t2 (j) SELECT 1 SELECT * FROM #t2 j ----------- 1 1 1 1 ALTER TABLE #t2 ADD i INT IDENTITY (5,2) SELECT * FROM #t2 j i ----------- ----------- 1 5 1 7 1 9 1 11 Это может оказаться полезным для таблиц с дубликатами строк. Замечание. Существующий столбец не может быть преобразован в столбец identity. В этом случае Вы должны удалить существующий столбец и добавить новый. При этом существующие значения не могут быть сохранены. Для сохранения существующих значений создают новую таблицу и вставляют в нее строки, используя identity_insert. Помимо этого, такое обновление всех строк в таблице может занять очень длительное время на больших таблицах и увеличить размер журнала транзакций. Select IntoСтолбец identity может быть включен в таблицу, создаваемую с помощью оператора select into посредством функции identity SELECT *, IDENTITY(INT,1,1) AS id INTO #tbl FROM sysobjects Это полезно для создания таблиц из уже существующих структур. Типы данных IdentityIdentity должен содержать только целочисленные значения, однако столбец может быть любого числового типа данных (bigint, int, tinyint, numeric, decimal). Это может оказаться полезным, когда значения превышают границу, допустимую для типа bigint. Поиск столбцов Identity и их свойствНаличие столбца identity в таблице может быть проверено следующим образом: SELECT OBJECTPROPERTY(OBJECT_ID(' Оператор вернет 1, если таблица содержит столбец identity. Аналогично... SELECT COLUMNPROPERTY(OBJECT_ID(' ... покажет, имеет ли столбец свойство identity . Более полезный способ получить эту информацию состоит в использовании каталожного представления sys.identity_columns, которое возвращает строку для каждого столбца в базе данных, имеющего свойство identity . SELECT TableName = OBJECT_NAME(OBJECT_ID) , ColumnName = name , OriginalSeed = seed_value , Step = increment_value , LastValue = last_value , IsNotForReplication = is_not_for_replication FROM sys.identity_columns Символьные значения в столбце IdentityОбщая проблема состоит в построении такого составного значения, которое будет содержать последовательные значения, зависящие от символьной составляющей, например, a1 a2 a3 b1 b2 Такое невозможно и, вероятно, даже не желательно. Заметьте, что этот столбец фактически содержит два значения - для чего бы это понадобилось? Возможно, это - попытка построить последовательность на символьной составляющей. Такое определение является ошибочным - последовательное значение не зависит от символьной составляющей и поэтому должно являться отдельным столбцом. Тогда мы можем использовать identity для числового значения и легко вычислить на основании этого последовательное значение, получая доступ к таблице или к представлению. Если требуется хранить последовательные значения в таблице, возможно, по соображениям производительности, то тогда это может быть выполнено посредством триггера. Bulk InsertЕсли таблица имеет столбец identity, то оператор bulk insert (массовая вставка) будет постоянно сбоить, если значения identity не будут содержаться в текстовом файле. Самый легкий путь решить проблему состоит в том, чтобы создать представление на таблице, которое бы не содержало столбца identity, и выполнять массовую вставку в представление. Другой вариант состоит в том, чтобы создать форматный файл, чтобы использовать его с bulk insert. Я по возможности избегал бы этого варианта, поскольку это добавляет внешний объект и делает поддержку более сложной. Этим предполагается, что значения identity будут располагаться в порядке строк текстового файла, но дело обстоит не так. Часто проблема возникает с неструктурированными данными, подобными XML. В этом случае блок XML не может быть разобран, используя значения identity. Это зачастую будет работать, но чего нельзя гарантировать - особенно, если будут порождаться многочисленные потоки, - поэтому лучше не полагаться на это. Для работы с такими данными импортируйте их в текстовый столбец (или varchar (max) в v2005 +), чтобы затем разобрать данные. Такой вариант может оказаться весьма медленным. Вы не сможете определить разделитель столбцов или строк, и имеется интересная "особенность" в некоторых версиях sql сервера, которую следует знать: Если длина текстового файла делится на 4, bulk insert потерпит неудачу, не выдавая ошибки. Проверьте вашу версию, чтобы убедиться в наличии этой проблемы, и, если это так, Вы можете проверить длину файла и добавить фиктивный символ, если длина файла оказывается делимой на 4. Использовать Identity или нетЭто вопрос, который часто вызывает страсти почти религиозного фанатизма, и поиск даст вам массу источников по этому поводу. Мне приходилось слышать, как люди утверждали, что каждая таблица в базе данных должна иметь столбец identity, и что только они должны использоваться в соединениях. Другие люди настаивают на том, что это не имеет никакого отношения к реляционной базе данных и никогда не должно использоваться. Я не подписался бы ни под одним из этих мнений, но буду использовать identity там, где это кажется разумным. Импортируя данные в промежуточные таблицы, identity может оказаться полезной для идентификации строк, которые могут содержать дубликаты. В той же самой ситуации это может быть полезным для группирования строк в соответствии с памятью, доступной для обработки. Поисковая таблица (lookup table) нуждается в ID, так почему бы не сделать его identity, если он не создается скриптом. Это может быть полезным для создания ID, например, идентификатора клиента, но следует быть осторожным в случае различных систем, использующих один и тот же ID. Восстановление после сбояВозможны проблемы с восстановлением после сбоя и резервными системами. Если значения identity используются в другой базе данных, тогда базы данных могут стать несогласованными. Когда резервная система переносится в онлайн, должно быть некоторое средство проверки, что значения находятся в согласованном состоянии. РезюмеПолезная информация§ Онлайновый выпуск рассылки можно почитать на сайте. § Все статьи, публикуемые в рассылке, затем выкладываются на сайте Книги и статьи по SQL. § Желающих поспособствовать популяризации сайта прошу проголосовать/поставить закладку в социальных сетях: КонтактыПо всем вопросам, связанным с функционированием сайта, проблемами при решении упражнений, идеями вы можете обращаться к Сергею И.Моисеенко msi77[@]yandex.ru. Вы также можете предложить свои задачи для публикации на сайте. |
В избранное | ||