Есть ли способ получить все хранимые процедуры, которые могут обновлять определенный столбец в SQL?

У меня есть поле в таблице, значение которого неожиданно изменилось. Ясно, что это вызвано хранимой процедурой (я уже просмотрел несколько триггеров, которые мы используем, и ни один логин не имеет разрешений на обновление ни для одной из таблиц в нашей базе данных), и я нахожусь в процессе поиска того, какой из них это сделал.

Если бы я был, скажем, в Visual Studio, я бы просто сделал «Найти все ссылки» в поле, и задача была бы легкой.

Есть ли эквивалентный инструмент для SQL? Я знаю о функции SSMS «найти зависимости объектов», но это будет возвращать хранимые процедуры (и представления) только с использованием таблицы, а не конкретного поля. (и, к сожалению, моя таблица объединена буквально тысячами SQL-запросов)

Имя столбца «Активен», поэтому текстовый поиск в моей схеме базы данных тоже не сильно поможет (у меня сотни таблиц с таким полем)

Итак, в основном я вижу два варианта:

  • написание сложного регулярного выражения для соответствия обновлениям. Написание такого регулярного выражения, вероятно, является огромной задачей (из-за всех тонкостей синтаксиса SQL).
  • используя инструмент, который делает именно это.

Знаете ли вы о таком инструменте (или таком регулярном выражении, или другом способе сделать это)?


person Brann    schedule 24.02.2011    source источник
comment
Ясно, что это вызвано хранимой процедурой - есть много клише о предположениях, большинство из которых, вероятно, будут отмечены моим комментарием.   -  person Damien_The_Unbeliever    schedule 24.02.2011
comment
Ты прав. Я добавил больше информации об этом (по сути, я уже обыскал несколько триггеров, которые мы используем, и ни один логин не имеет доступа для записи в какую-либо таблицу)   -  person Brann    schedule 24.02.2011
comment
Что вы можете сделать, так это ограничить пересечение модулей SQL, содержащих UPDATE, TableName и Active. Это, вероятно, сузило бы его настолько, насколько вы можете.   -  person Cade Roux    schedule 24.02.2011


Ответы (6)


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

Вы можете использовать триггер для отслеживания изменений в столбце. Я использовал триггеры, созданные AutoAudit, чтобы иметь возможность отслеживать изменения.

Преимущество триггера заключается в том, что он находится на уровне таблицы и является частью схемы базы данных, независимо от того, как запрашиваются изменения в таблице и независимо от механизма подключения — связанной таблицы ODBC/ADO/SP/Agent Job/Access, и т.п.

person Cade Roux    schedule 24.02.2011
comment
Действительно, ни один логин не имеет доступа для записи в таблицу, и мы не используем триггеры (я обновил свой первоначальный вопрос, чтобы уточнить это). Я согласен, что некоторые триггеры могут помочь в таком процессе отладки, но они не будут работать для отслеживания ошибок, которые уже произошли. - person Brann; 24.02.2011
comment
и проблема с поиском всех процедур заключается в том, что у меня есть сотни процедур, зависящих от этой таблицы. Большинство этих процедур имеют запросы, присоединяющиеся к этой таблице в поле Active=1. - person Brann; 24.02.2011
comment
@ Бранн Нет простого пути. Если у ваших SP есть соглашение об именах, вам нужно проверить только те, которые являются обновлениями. Что мне нравится видеть, так это базовые CRUD SP для каждой таблицы, отчетные SP, которые объединяют множество таблиц (но никогда не INSERT/UPDATE), а затем некоторые пакетные или бизнес-/транзакционные SP, которые выполняют массовые операции или многоэтапные операции (перенос запасов или что-то в этом роде). как это). Очевидно, что если это происходит там, где этого быть не должно, никакие условности мира не помогут. - person Cade Roux; 24.02.2011
comment
@Brann Чтобы помочь со многими отфильтрованными объединениями Active = 1 (оглядываясь назад), можно было бы обернуть это в представление ActiveWhatever и вместо этого всегда присоединяться к нему. Но такой рефакторинг требует времени. - person Cade Roux; 24.02.2011

Одним из подходов «бедняка» к этому было бы удалить столбец из копии вашей базы данных, а затем попытаться найти сохраненные процедуры, которые больше не работают. Существует статья проекта кода, в которой утверждается, что она может проверить все сохраненные процессы для вас. , или вы можете взять концепцию, изложенную там, и построить ее полностью как сценарий T-SQL, который выдает сценарий T-SQL, который затем выдает ошибку в соответствующих местах.


Из комментария — в этом случае замените активный столбец вычисляемым столбцом. Например.:

ALTER TABLE TableName DROP COLUMN Active
GO
ALTER TABLE TableName ADD Active as CAST(1 as bit)

(Или любой другой подходящий тип данных). Это сломает операторы DML, в то время как SELECTs все еще будут работать.

person Damien_The_Unbeliever    schedule 24.02.2011
comment
Дело в том, что это нарушит все процедуры, основанные на доступе READ к моему столбцу. Я пытаюсь найти только процедуры, требующие доступа для записи. - person Brann; 24.02.2011
comment
использование вычисляемых столбцов — отличная идея! +1 от меня - person Brann; 24.02.2011

SQL Prompt 5 имеет Функция зависимостей столбцов, которая может вам подойти.

person David Atkinson    schedule 24.02.2011

Проверьте sys.sql_dependencies. Что-то типа

select object_name(o.object_id)
from sys.sql_dependencies sd
inner join sys.objects o
   on sd.referenced_major_id = o.object_id
inner join sys.columns c
   on o.object_id = c.object_id
   and sd.referenced_minor_id = c.column_id
where o.name = 'your_table_here'
   and c.name = 'your_column_here'

Вероятно, было бы неплохо вызвать sp_refreshsqlmodule для всех ваших хранимых процедур, чтобы убедиться, что sys.sql_dependencies обновлена. Кроме того, имейте в виду, что этот метод не будет перехватывать какой-либо динамический sql, поэтому, если это вас беспокоит, вам нужно найти другой метод.

person Ben Thul    schedule 24.02.2011
comment
Это прекрасно работает в SQL Server 2008! Однако вы должны квалифицировать эту первую ссылку на object_id. - person catfood; 24.05.2012

Попробуй это:

SELECT DISTINCT so.name
FROM sys.syscomments sc
INNER JOIN sys.objects so on sc.id=so.object_id
WHERE sc.text LIKE '%colToSearchFor =%'

Это предполагает, что между именем столбца и знаком равенства есть пробел, поэтому вам также нужно будет запустить его без пробела или с большим количеством пробелов/табуляций и т. д. Тем не менее это лучше, чем ничего.

person Trent    schedule 18.03.2013

Redgate предоставляет инструмент поиска SQL, поэтому вы можете искать свой код sql в базе данных по имени столбца, который может быть ответом. Либо так, либо щелкните правой кнопкой мыши и запишите всю базу данных в файл и найдите в этом файле.

Я бы тоже не ограничивался СП. Сколько раз у меня была эта проблема, и она сводилась к забытому триггеру (триггеры grr...)...

person Paddy    schedule 24.02.2011