update top inner example ejemplos delete sql-server sql-server-2008 stored-procedures sql-server-2005 sp-msforeachtable

top - SQL Server sp_msforeachtable use para seleccionar solo aquellas tablas que cumplan con alguna condiciĆ³n



update sql (2)

Estoy intentando escribir esta consulta para encontrar todas las tablas con una columna específica con algún valor específico. Esto es lo que he hecho hasta ahora.

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 ''

Espero que mis intenciones sean claras, solo quiero seleccionar aquellas tablas donde está presente la columna EMP_CODE y en esas tablas quiero seleccionar aquellas filas donde EMP_CODE=''HO081'' .

Editar -

Ahora está así. Pero no puedo reemplazar la variable @EMPCODE en la consulta.

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+'''''')''


¿Sabe cómo sp_MSforeachtable no está documentado y puede desaparecer en cualquier momento / ser modificado?

Bueno, si está @whereand a ignorarlo, tiene otro parámetro llamado @whereand , que se adjunta a la cláusula WHERE de la consulta interna que se está utilizando para encontrar las tablas (y debe comenzar con un AND ).

También debes saber que hay un alias, o contra sysobjects , y un segundo alias syso contra sys.all_objects .

Usando este conocimiento, puede crear su parámetro @whereand como:

EXEC sp_MSforeachtable @command1=''...'', @whereand=''AND o.id in (select object_id from sys.columns c where c.name=''''EMP_CODE'''')''

Ahora también puede simplificar su command1 , ya que sabe que solo se ejecutará en tablas que contengan una columna EMP_CODE . Probablemente eliminaría la condición COUNT(*) también, ya que no veo qué valor está agregando.

Actualizado en base a su trabajo posterior, y probado en una tabla:

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'''')''

(He revertido @whereand para consultar EMP_CODE , ya que no desea reemplazar el valor allí).

El problema es que puede pasar parámetros a un procedimiento almacenado, o literales , pero no puede realizar cálculos / acciones combinadas entre ellos, por lo que trasladé la construcción de la declaración SQL a una acción separada.


Supongo que recibe un error de algún tipo, ¿tal vez un Invalid column name ''EMP_CODE'' ?

Es porque el código se compila antes de verificar la columna. Podrías hacer esto así.

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 ''