Использование SQL Server sp msforeachtable для выбора только тех таблиц, которые удовлетворяют некоторым условиям
Я пытаюсь написать этот запрос, чтобы найти все таблицы с определенным столбцом с определенным значением. Вот что я сделал до сих пор ... --6-->
EXEC sp_MSforeachtable
@command1='
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE")
BEGIN
IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0
BEGIN
SELECT * FROM ? WHERE EMP_CODE="HO081"
END
END
'
надеюсь, мои намерения ясны, я просто хочу выбрать только те таблицы, где столбец EMP_CODE
присутствует и в этих таблицах, я хочу, чтобы выбрать строки, где EMP_CODE='HO081'
.
изменить -
теперь он стоит так. Но я не могу заменить @EMPCODE
переменной в запрос.
DECLARE @EMPCODE AS VARCHAR(20)
SET @EMPCODE='HO081'
EXEC sp_MSforeachtable
@command1='
DECLARE @COUNT AS INT
SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+'''
IF @COUNT>0
BEGIN
PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)''
--PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+'''''''
END
',@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME='''+@EMPCODE+''')'
2 ответов
ты знаешь, как sp_MSforeachtable
является недокументированным и может уйти в любое время/быть изменен?
Ну, если вы счастливы игнорировать это, у него есть другой параметр под названием @whereand
, который прилагается к WHERE
предложение внутреннего запроса, который используется для поиска таблиц (и должен начинаться с AND
).
вы также должны знать, что есть псевдоним, o
против sysobjects
, и второй псевдоним syso
против sys.all_objects
.
С помощью этого знание, вы могли бы создать свой @whereand
параметр as:
EXEC sp_MSforeachtable
@command1='...',
@whereand='AND o.id in (select object_id from sys.columns c where c.name=''EMP_CODE'')'
теперь вы можете упростить ваш command1
, так как вы знаете, что он будет работать только против таблиц, содержащих . Я бы, наверное, вынул COUNT(*)
условие также, так как я не вижу, какое значение он добавляет.
обновлено на основе вашей дальнейшей работы и протестировано против одной таблицы:
DECLARE @EMPCODE AS VARCHAR(20)
SET @EMPCODE='HO081'
declare @sql nvarchar(2000)
set @sql = '
DECLARE @COUNT AS INT
SELECT @COUNT=COUNT(*) FROM ? WHERE EMP_CODE='''+@EMPCODE+'''
IF @COUNT>0
BEGIN
PRINT PARSENAME("?",1)+'' => ''+CONVERT(VARCHAR,@COUNT)+'' ROW(S)''
--PRINT ''DELETE FROM ''+PARSENAME("?",1)+'' WHERE EMP_CODE='''''+@EMPCODE+'''''''
END
'
EXEC sp_MSforeachtable
@command1=@sql,@whereand='AND O.ID IN (SELECT OBJECT_ID FROM SYS.COLUMNS C WHERE C.NAME=''EMP_CODE'')'
(я вернул @whereand
на запрос EMP_CODE
, так как вы не хотите заменить значение там).
проблема в том, что вы можете пройти параметры в хранимой процедуре, или литералы, но вы не можете выполнять вычисления/комбинировать действия между ними - поэтому я переместил построение инструкции sql в отдельное действие.
Я думаю, вы получаете какую-то ошибку, возможно Invalid column name 'EMP_CODE'
?
это потому, что код компилируется перед проверкой столбца. Ты мог бы сделать вот так.
EXEC sp_MSforeachtable
@command1='
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=PARSENAME("?",2) AND TABLE_NAME=PARSENAME("?",1) AND COLUMN_NAME="EMP_CODE")
BEGIN
EXEC(''
IF (SELECT COUNT(*) FROM ? WHERE EMP_CODE="HO081")>0
BEGIN
SELECT * FROM ? WHERE EMP_CODE="HO081"
END
'')
END
'