Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Вопросы и ответы по MS SQL Server" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
MS SQL Server - дело тонкое...
#065<< #066 |
СОВЕТЫ
Древовидные структуры в SQL
По материалам статьи Joe Celko на intelligententerprise.com "
Trees in SQL" Обзор некоторых общих вопросов, касающихся древовидных структур и иерархии в SQL. Эта тема уже рассматривалась мной ранее, но она заслуживает повторения. В специализированных конференциях я встречал слишком много вопросов о древовидных структурах и иерархии в SQL. В литературе по SQL приводится стандартная модель древовидной структуры, которая называется список смежных вершин графа и выглядит следующим образом: CREATE TABLE Personnel
Таблица 1. Список смежных вершин графа Другим способом представления древовидной структуры являются вложенные множества. Поскольку SQL является языком, предназначеным для работы со множествами, то эта модель является более предпочтительной, чем стандартный пример списка смежных вершин графа, который более часто встречается в литературе. Давайте создадим тестовую таблицу Personnel, не обращая пока внимания на поля lft и rgt: CREATE TABLE Personnel Эта проблема часто описывается в учебниках с помощью поля для Сотрудника (Personnel emp) и одного из его Начальников (Boss). Следующая таблица (Таблица 2) - за исключением полей lft и rgt - в теории графов называется список смежных вершин графа или пары вершин графа, смежные друг другу.
Таблица 2. Вложенные множества Структура организации может быть представлена в виде направленного графа, как показано на рис.1 Albert (1, 12) ¦ -------------+--------------- ¦ ¦ ¦ ¦ Bert (2, 3) Chuck (4, 11) ¦ --------------------------------------------------------- ¦ ¦ ¦ ¦ ¦ ¦ Donna (5, 6) Eddie (7, 8) Fred (9, 10) Таблица 1 является денормализованной по нескольким направлениям. Мы моделируем структуру персонала и организации в одной таблице. Ради экономии дискового пространства представим себе, что имя сотрудника является также названием его должности и что мы имеем еще одну таблицу, которая содержит информацию о сотрудниках и занимаемых ими должностях. Еще одной проблемой, связанной с моделью "Список смежных вершин графа" является то, что поля Начальник (Boss) и Сотрудник (Personnel emp) содержат данные одинакового вида (имя сотрудника) и поэтому эти данные должны располагаться в одном и том же поле нормализованной таблицы. Для подтверждения того, что эти данные не нормализованы, предположим, что "Chuck" изменил свое имя на "Charles"; вы должны изменить его имя в обеих полях и в нескольких местах. По определению, в нормализованной таблице одна сущность должна встречаться лишь однажды и только в одном месте. Последней проблемой является то, что "Список смежных вершин графа" не является подчиненной (субординационной) моделью. Полномочия передаются сверху вниз в иерархическом порядке, но если я уберу сотрудника по имени "Chuck", я разорву всю его подчиненность от сотрудника по имени "Albert". В некоторых случаях (например, для трубопроводов) это справедливо, но в нашем случае мы не предполагаем такой ситуации. Чтобы изобразить древовидную структуру в виде вложенных множеств, заменим вершины графа овалами, где подчиненные овалы вложены один в другой. Основание дерева будет представлено самым большим овалом, который содержит все остальные овалы. Концевые вершины будут представлены самыми внутренними овалами, не содержащими внутри никаких других овалов, а вложенность будет показана иерархическими взаимоотношениями. Поля rgt и lft (я не использую зарезервированные слова RIGHT и LEFT) - это именно то, что показывает вложенность. Если эта образная модель не работает, то представьте себе маленького червя, ползущего вдоль дерева против часовой стрелки. Каждый раз, когда он достигает правую или левую сторону вершины, он нумерует ее. Червь останавливается после того, когда он обойдет вокруг всего дерева и вернется назад к основанию. Эта модель натуральным образом показывает как увеличивается количество частей, потому что последняя сборка состоит из вложенных сборок, которые, в конечном итоге, состоят из отдельных частей. Теперь мы видим, что поле Начальник (Boss) является избыточным и денормализованным, следовательно оно может быть удалено. Обратите также внимание на то, что древовидная структура может быть размещена в одной таблице, а вся информация о вершинах графа может быть помещена в другую таблицу. Вы можете связать обе таблицы между собой по номеру сотрудника. Для преобразования графа в модель вложенных множеств вспомните о маленьком червячке, ползущем вдоль дерева. Червь начинает двигаться сверху - от основания - и обползает вокруг всего дерева. Когда он приходит к вершине, он присваивает значение стороне, которую он посещает и увеличивает значение счетчика на единицу. Каждая вершина получает два значения - одно для правой стороны и одно для левой. (Специалисты называют это модифицированным алгоритмом обхода вершин графа в прямом порядке.) И в заключение, удалим за ненадобностью поле "Personnel.Boss", которое представляло ребро графа.
Это дает нам некоторые предсказуемые результаты, которые мы можем использовать при построении
запросов. Основание всегда можно представить в виде: 1. Найти сотрудника и всех его начальников, независимо от глубины вложения. SELECT P2.* FROM Personnel AS P1, Personnel AS P2 WHERE P1.lft BETWEEN P2.lft AND P2.rgt AND P1.emp = :myemployee; 2. Найти сотрудника и всех его подчиненных. (Этот запрос симметричен первому.) SELECT P1.* -- (В оригинале опечатка: SELECT P2.*) FROM Personnel AS P1, Personnel AS P2 WHERE P1.lft BETWEEN P2.lft AND P2.rgt AND P2.emp = :myemployee; 3. Добавьте GROUP BY и обобщенные функции к этим базовым запросам и вы получите иерархические отчеты. Например, суммарный лимит заработной платы, которой распоряжается каждый сотрудник: SELECT P2.emp, SUM(S1.salary) FROM Personnel AS P1, Personnel AS P2, Salaries AS S1 WHERE P1.lft BETWEEN P2.lft AND P2.rgt AND P1.emp = S1.emp GROUP BY P2.emp; 4. Найти уровень (глубину вложения) каждой вершины, что дает возможность распечатать древовидную структуру как листинг с отступами. SELECT COUNT(P2.emp) AS indentation, P1.emp FROM Personnel AS P1, Personnel AS P2 WHERE P1.lft BETWEEN P2.lft AND P2.rgt GROUP BY P1.emp ORDER BY P1.emp; -- (В оригинале опечатка: ORDER BY P1.lft)5. Модель вложенных множеств содержит неявный порядок смежных вершин, которого нет в модели "Список смежных вершин графа". Добавление новой вершины как смежной крайней правой: BEGIN DECLARE right_most_sibling INTEGER; SET right_most_sibling = (SELECT rgt FROM Personnel WHERE emp = :your_boss); UPDATE Personnel SET lft = CASE WHEN lft > right_most_sibling THEN lft + 2 ELSE lft END, rgt = CASE WHEN rgt >= right_most_sibling THEN rgt + 2 ELSE rgt END WHERE rgt >= right_most_sibling; INSERT INTO Personnel (emp, lft, rgt) VALUES ('New Guy', right_most_sibling, (right_most_sibling + 1)) END; 6. Для преобразования модели "Список смежных вершин графа" в модель вложенных множеств можно использовать a push down stack алгоритм. Предположим, что мы имеем следующую таблицу: -- Древовидная структура содержащая модель "Список смежных вершин графа" CREATE TABLE Tree (emp CHAR(10) NOT NULL, boss CHAR(10)); INSERT INTO Tree SELECT emp, boss FROM Personnel; -- Stack starts empty, will holds the nested set model -- Изначально стек пустой, он будет содержать модель вложенных множеств CREATE TABLE Stack (stack_top INTEGER NOT NULL, emp CHAR(10) NOT NULL, lft INTEGER, rgt INTEGER); BEGIN ATOMIC DECLARE counter INTEGER; DECLARE max_counter INTEGER; DECLARE current_top INTEGER; SET counter = 2; SET max_counter = 2 * (SELECT COUNT(*) FROM Tree); SET current_top = 1; INSERT INTO Stack SELECT 1, emp, 1, NULL FROM Tree WHERE boss IS NULL; DELETE FROM Tree WHERE boss IS NULL; WHILE counter <= (max_counter - 2) LOOP IF EXISTS (SELECT * FROM Stack AS S1, Tree AS T1 WHERE S1.emp = T1.boss AND S1.stack_top = current_top) THEN BEGIN -- push when top has subordinates, set lft value -- вершина имеет подчиненные вершины, -- заносим новое значение lft в стек INSERT INTO Stack SELECT (current_top + 1), MIN(T1.emp), counter, NULL FROM Stack AS S1, Tree AS T1 WHERE S1.emp = T1.boss AND S1.stack_top = current_top; DELETE FROM Tree WHERE emp = (SELECT emp FROM Stack WHERE stack_top = current_top + 1); SET counter = counter + 1; SET current_top = current_top + 1; END ELSE BEGIN -- pop the stack and set rgt value -- выталкиваем значение из стека и определяем значение rgt UPDATE Stack SET rgt = counter, stack_top = -stack_top -- pops the stack WHERE stack_top = current_top SET counter = counter + 1; SET current_top = current_top - 1; END IF; END LOOP; END; Несмотря на то, что эта процедура работает, вы можете переписать ее на языке, позволяющем работать с массивами, вместо того, чтобы придерживаться чистого SQL. Копирование базы данных MS SQL Server
По материалам статьи Rahul Sharma на sqlservercentral.com: "
Copying a Database from Server to Server" В этой статье автор рассматривает несколько возможных вариантов копирования баз данных MS SQL Server с одного сервера на другой. Метод 1: самый быстрый способ копирования - отсоединение базы данных от исходного сервера и затем прикрепление вместе с журналом на нужный сервер. Отсоедините базу данных на исходном сервере (Измените, соответственно, имя базы данных): Use Master GO Exec sp_detach_db 'database_name', 'true' GO
sp_detach_db отсоединяет базу данных от исходного сервера (у неё два параметра: @dbname, который
является именем базы данных и @skipchecks, который является указанием для обновления статистики)
и указав значение 'true' для второго параметра (@skipchecks) этой хранимой процедуры, что бы
удостоверится в том, что если модификация статистики не была выполнена перед отсоединением базы
данных от сервера, она обновится после присоединения, что потребует некоторого времени.
Скопируйте данные и журналы из каталога Data исходного сервера в каталог данных на новом сервере.
Удостоверитесь, что Вы не имеете точно таких же баз данных на сервере адресата.... Если это так,
отключите их. Use Master GO PRINT 'Attaching Database' EXEC sp_attach_db @dbname = 'database_name', @filename1 = 'c:\mssql7\data\database_name.mdf', -- Это путь к файлу данных @filename2 = 'd:\mssql7\data\database_name_log.ldf' -- Это путь к журналу Этим Вы прикрепите базу данных к новому серверу, но учётные данные пользователей, для подключения к базе не будут скопированы с исходного на новый сервер. Вы можете использовать нижеследующий сценарий, чтобы перенести логины:
/* Установите связанный сервер (используя sp_addlinkedserver и sp_addlinkedsrvlogin),
назвав его: sourceserver, и из которого стандартные логины входа в систему должны
быть перенесены. Вы можете называть его, как Вам удобно и изменить также имя
связанного сервера. Чтобы обеспечить доступу к данным связанного сервера, Вы
должны использовать sp_serveroption */
declare @login sysname , @password sysname declare sourcelogins cursor for select name , password from sourceserver.master.dbo.syslogins where isntname = 0 and charindex( 'repl_' , name ) = 0 and charindex( 'distributor' , name ) = 0 and name != 'sa' open sourcelogins while ( @@fetch_status = 0) begin fetch sourcelogins into @login , @password exec sp_addlogin @login , @password , @encryptopt = 'skip_encryption' end close sourcelogins deallocate sourcelogins go
При откреплении и прикреплении баз данных, я столкнулся с ещё одной проблемой, кроме потери
связи пользователей и их логинов, описанной выше. Я обнаружил, что статистика останется не
эффективной, если Вы выполните sp_updatestats на прикрепляемой базе данных. Так, я рекомендовал
бы обновить статистику после того, как Вы уже прикрепили эту базу. Или воспользуйтесь
альтернативным вариантом: когда Вы открепляете базу данных, удостоверьтесь, что второй параметр
установлен в Ложь, что заставит статистику обновиться, и Вам не придётся обновлять её позже на
новом сервере. Любой из этих путей прекрасно работает. Метод 2: Использование DTS.
DTS очень часто используется для перемещения баз данных с сервера на сервер. Вы можете использовать
мастер экспорта/импорта DTS (SQL 7.0 и 2000). Мастер может использоваться для копирования схем,
объектов (хранимые процедуры, представления и триггеры и т.д.), данных и также логинов. Или Вы
можете использовать DTS Designer и создать задачу перемещения базы данных и задачу перемещения
логинов (доступно только для SQL 2К). Также, Вы можете использовать мастер копирования баз
данных (Copy Database Wizard), чтобы решить задачу перемещения базы (доступно только для
SQL 2К). DTS - довольно мощный инструмент и если Вы его пока не использовали, Вы лишаете себя
многих функциональных возможностей и лёгкости, с которой Вы могли бы решать сложные задачи. Метод 3: Создайте схему и механизм переноса данных, использующий bcp/bulk insert.
Создайте схему на сервере приёмнике данных, если Вы уже имеете скрипт для создания схемы и затем
используете bcp или bulk insert, чтобы скачать данные. Оба операции - нерегистрируемые, так что они
отработают очень быстро. Главное различие между bcp и bulk insert - это то, что bulk insert не может
экспортировать данные, а bcp может. Метод 4: Традиционный путь: Backup и Restore. Сделайте полную копию базы данных, и затем восстановите её на новом сервере. Метод 5: Использование распределённых запросов. Вы сначала должны создать схему на сервере приёмнике данных, используя ваши скрипты создания схем. После этого Вы можете организовать связанный сервер и написать инструкции вставки, которые будут вставлять данные из источника на новый сервер, используя функции openrowset и openquery для запросов к связанным серверам. Вы должны удостовериться, что foreign key и check constraints отключены до того, как Вы начнёте закачивать данные и затем подключить их, когда всё будет сделано. Этот метод самый медленный из всех упомянутых в этой статье. Зато, с помощью него можно переносить данные на SQL Server из гетерогенных источников, например: Oracle, Sybase, DB2 и т.д. ССЫЛКИ НА СТАТЬИ
Проблема создания современных бизнес-приложений СУБД Новые технические статьи Microsoft INF: How to Work with More Than 64,000 Children Per Parent (Q303969) INF: Disaster Recovery Articles for Microsoft SQL Server (Q307775) INF: File Size Limitations For Use of Archive/Restore for OLAP (Q303415) FIX: "Unable To Run The Script Files" Error Message Occurs with Desktop Engine Modification (Q306491) INF: Use of Multiple Hierarchies Versus the Creation of Separate Hierarchies (Q306408) INFO: SQL Server CE Performance Tips and Efficient Memory Handling (Q274112) PRB: Scheduled Tape Backup Waits Indefinitely if No Tape is in Drive (Q281665) FIX: Full-Text Search Queries with CONTAINS Clause Search Across Columns (Q294809) HOW TO: Prebuild a SQL Server CE Database (Q301217) Support WebCast: Understanding INSTEAD OF Triggers in Microsoft SQL Server 2000 Support WebCast: Microsoft SQL Server 2000 Windows CE Edition Overview and Programming Support WebCast: Troubleshooting Distributed Queries in SQL Server 7.0 Support WebCast: Microsoft SQL Server 2000 Log Shipping Support WebCast: Multi-instancing in Microsoft SQL Server 2000 Support WebCast: Microsoft SQL Server 2000: Merge Replication Enhancements Support WebCast: Microsoft SQL Server 2000: New XML Features Support WebCast: Analyzing Optimal Compiled Plan Caching Support WebCast: Understanding User-Defined Functions in Microsoft SQL Server 2000 Support WebCast: Introduction to Microsoft SQL Server 2000 Clustering Support WebCast: How to Effectively Use SQL Server Profiler Support WebCast: Effective Indexing and Statistics with SQL 2000 Support WebCast: Implementing ADOX in Jet and SQL Server Applications Support WebCast: How to Collect and Analyze Performance Data in Microsoft SQL Server Support WebCast: Microsoft SQL Server 7.0 Common Problems and Resolutions Support WebCast: Optimizing SQL Server 7.0 on Windows 2000 Advanced Server and Windows 2000 Datacenter Server Support WebCast: Troubleshooting Microsoft SQL Mail Support WebCast: Accessing and Manipulating Data in Microsoft SQL Server 2000 Databases by Using SQLXML UpdateGrams Support WebCast: Inside Microsoft SQL Server 6.5 Replication Support WebCast: Cascading Referential Integrity Constraints in SQL Server 2000 Support WebCast: SQL Server 7.0 Full-Text Search and Basic Troubleshooting Methods Support WebCast: SQL Server 2000 Profiler: What's New and How to Effectively Use It Support WebCast: SQL Server 2000 Database Recovery: Backup and Restore Support WebCast: SQL Server 7.0: Features of Data Transformation Services PRB: Error When You Implement Nested Transaction with OLE DB Provider for SQL Provider (Q306649) INF: How to Change Network IP Addresses on a Virtual SQL Server (Q244980) FIX: Distribution Agent Ignores Quoted Identifier Option on Initial Sync to Oracle Subscribers (Q278509) FIX: SQL Server ODBC Driver Reuses Incorrect Parameter Length (Q280294) INF: List of Bugs Fixed in SQL Server 2000 Service Pack 1 (1 of 2) (Q290212) HOWTO: Configure MSDTC in a Windows 2000 Cluster Environment (Q290624) PRB: Subquery with Non-existent Column Returns Results Instead of Error Message (Q298674) FIX: SQL Server Performance Condition Alerts do not Fire After You Install SQL Server 2000 Service Pack 1 (Q303005) FIX: SP1 Regression: Table Scan Chosen Over Index Seek for INSERT/SELECT Statement Against the Same Table (Q306374) FIX: ISQLWCE for PocketPC SH3 Has Incorrect MFC and OLE DLLs (Q292616) BUG: Error Message 7355 "..Inconsistent metadata for a column" Occurs When You Use a Linked Server (Q306401) FIX: Reinstall with Long Command May Cause Setup to Fail (Q306488) BUG: Objects May Fail to Retain Quoted Identifier Setting When You Use SQL-DMO to Create or Alter Objects (Q306334) ФОРУМ SQL.RU: САМЫЕ ПОПУЛЯРНЫЕ ТОПИКИ НЕДЕЛИ
Refresh
таблиц или аналог IBEvents для MSSQL ФОРУМ SQL.RU: ВОПРОСЫ ОСТАЛИСЬ БЕЗ ОТВЕТА
Русский
текст в таблице < |
#065<< #066 |
|
http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу | Рейтингуется SpyLog |
В избранное | ||