Pull to refresh
96
0
Send message
На уровне метаданных, в SQL Server существуют понятия soft и hard зависимостей. Последние всегда валидируют связанные объекты при их изменении или попытке удаления.

Пример таких зависимостей – скалярная функция, которая используется в COMPUTED столбце:

CREATE FUNCTION dbo.udf_Computed (@a INT)
RETURNS INT
AS BEGIN
	RETURN @a
END
GO

CREATE TABLE dbo.tbl_Table (
    ID INT,
    Value AS dbo.udf_Computed(ID)
)
GO

DROP FUNCTION dbo.udf_Computed
GO

Msg 3729, Level 16, State 1, Line 2
Cannot DROP FUNCTION 'dbo.udf_Computed' because it is being referenced by object 'tbl_Table'.

В свою очередь, soft зависимости таким свойством не обладают. На практике же, существует большое количество нюансов с которыми я столкнулся, когда реализовывал поиск зависимостей в этом туле. Если будет желание могу описать такие случаи в отдельном посте по мере появления свободного времени.

К минусам неплохо было-бы прикреплять свои комментарии :)
Спасибо за статью. Хотел бы обратить Ваше внимание на несколько нюансов (insertRandomData).

Системное представление sys.all_objects содержит в себе и пользовательские и системные объекты. А поскольку фильтром Вы оставляете только пользовательские таблицы (type = 'U'), то целесообразно делать выборку из sys.objects. За счет этого Вы получите более эффективный план выполнения.

Также меня немного настораживает соединение с systypes. Возможно Вы хотели сделать соединение по user_type_id. В противном случае, возможна ситуация когда можно получить дублирование строк.

В общем, мой вариант Вашего запроса:

SELECT c.column_id
     , c.name
     , TYPE_NAME(c.user_type_id)
     , c.max_length
FROM sys.objects o
JOIN sys.columns c ON c.[object_id] = o.[object_id]
WHERE o.[type] = 'U'
    AND TYPE_NAME(c.system_type_id) != 'sysname'
    AND o.name LIKE @childTableName 
ORDER BY c.column_id;
Предложение весьма хорошее. Подумаем на досуге об этом :)
С другой стороны функция, которая я применял полностью не документирована, поэтому точно сказать не смогу.
Такой вариант, конечно, возможен. Однако, я считаю, что вероятность возникновения такой ситуации относительно невелика.
Вначале просто не о том подумал. Да такой вариант был бы быстрее.
Замечание верное. Так изначально и планировалось, но как-то не срослось, потому что перед вставкой нового профиля делается проверка — существует ли уже такой профиль в таблице. Делать это по хешу оказалось быстрее.
Познавательно. Спасибо за пост
Спасибо. Учту данное пожелание, когда буду подготавливать пост по бекапам.
Тут скорее важен не размер базы, а размер отдельных таблиц. которые имеют большой размер и неприятную особенность — в них часто изменяются данные. Именно для таких таблиц — целесообразно делать дефрагментацию индексов.
Спасибо за замечание. Такое поведение действительно весьма уместно в определенных сценариях.
Возможна ситуация когда есть триггер, который логирует изменения на базе либо делает еще что-то:

CREATE TRIGGER ddl_Server
    ON ALL SERVER 
    FOR ALTER_INDEX
AS
BEGIN
    RAISERROR('Error', 16, 1)
END

GO

ALTER INDEX ... ON .... REORGANIZE

В такой ситуации мы вообще не сможем изменить никаких индексов:

Msg 50000, Level 16, State 1, Procedure ddl_Server, Line 7 Error
Присоединяюсь к alan008. Возможно Вы имели ввиду триггера уровня базы/сервера, которые отслеживают события ALTER_INDEX?
Небольшое замечание — при пересоздании таблицы, впрочем, как и любого другого объекта — меняется его object_id.
Попробуйте несколько раз выполнить этот скрипт, чтобы увидеть описанную ситуацию:

IF OBJECT_ID('dbo.test1', 'U') IS NOT NULL
	DROP TABLE dbo.test1
GO

CREATE TABLE dbo.test1
(
	ID INT,
	CONSTRAINT PK_test1_ID PRIMARY KEY (ID)
)
GO

SELECT OBJECT_ID('dbo.test1')


Поэтому, во избежание коллизий, желательно привязываться не к object_id, а к полному имени объекта (схема + имя).
К минусам неплохо было-бы прикреплять свои комментарии :)
Возможно у Вас выставлен режим совместимости с SQL Server 2000?

О чем вы вообще? Я о CK и DF, вы вдруг о PK…

Спасибо за замечание. Немного поправил скрипт. Для Вашего примера мы получаем следующий скрипт:

CREATE TABLE [dbo].[test]
(
      [id1] [INT] NOT NULL IDENTITY(100,12)
    , [id2] [INT] NOT NULL
    , [id3] [INT] NOT NULL CONSTRAINT [df_test_id3] DEFAULT ((42)) CONSTRAINT [ck_test_id3] CHECK ([id3]<>(7))
    , [id4] [INT] NOT NULL
    , CONSTRAINT [pk_test] PRIMARY KEY NONCLUSTERED ([id2])
);


PS. Генерацию остальных индексов планирую добавить в продолжении.

Information

Rating
Does not participate
Registered
Activity