amikor a következő szkriptet futtatom, az jól fut:

declare @temp table ( name varchar(255), field varchar(255), filename varchar(255), filegroup varchar(255), size varchar(255), maxsize varchar(255), growth varchar(255), usage varchar(255) ); INSERT @temp exec sp_msforeachdb @command1="use ?; Exec sp_helpfile;" 

de amikor Saját sp_foreachdb eljárást használok, a forráskód az alábbi linken található:

Megbízhatóbb és rugalmasabb sp_MSforeachdb

declare @temp table ( name varchar(255), field varchar(255), filename varchar(255), filegroup varchar(255), size varchar(255), maxsize varchar(255), growth varchar(255), usage varchar(255) ); INSERT @temp exec sp_foreachdb @command="use ?; Exec sp_helpfile;" 

Kivételt kapok (kérjük, vegye figyelembe, hogy kivételkezelést adtam hozzá az eljáráshoz)

--EXCEPTION WAS CAUGHT-- THE ERROR NUMBER:8164 SEVERITY: 16 STATE: 1 PROCEDURE: sp_foreachdb LINE NUMBER: 165 ERROR MESSAGE: An INSERT EXEC statement cannot be nested. ------------------------------------ the sql ------------------------------------ SELECT name FROM sys.databases WHERE 1=1 AND state_desc = N"ONLINE" AND is_read_only = 0 Msg 16916, Level 16, State 1, Procedure sp_foreachdb, Line 239 A cursor with the name "c" does not exist. Msg 16916, Level 16, State 1, Procedure sp_foreachdb, Line 240 A cursor with the name "c" does not exist. (0 row(s) affected) 

Megjegyzések

  • Nem ‘ nem tudom, miért használod ‘ ezt a tekervényeset módszer. Miért ne csak a sys.master_files lekérdezést jelentené?
  • @Nic jól rámutatott, azonban én csak az sp_helpfile példát használtam. a való életben ez az egyik saját tárolt eljárásunk, amelyet hívnék

Válasz

A forráskód mert Aaron “s sp_foreachdb a következő sort tartalmazza:

INSERT #x EXEC sp_executesql @sql;

Az Ön véleménye szerint hibaüzenet:

Az INSERT EXEC utasítás nem ágyazható be.

Tehát az alábbi kód nem lesz érvényes, mivel INSERT xxx EXEC xxx kódot fészkel.

INSERT @temp exec sp_msforeachdb @command1="use ?; Exec sp_helpfile;" 

Megjegyzések

  • @marcellomiorelli Úgy gondolom, hogy a dinamikus SQL eltávolításához nagy változtatásra lenne szükség Aaron ‘ SP-jén. Ehhez valószínűleg a egy további függvény.

Válasz

Ha saját szerveréhez csatlakozik elosztott lekérdezési módszerekkel, akkor az trükk, ha sp_foreachdb egyetlen eredményt adna vissza.

create table #temp ( name varchar(255), field varchar(255), filename varchar(255), filegroup varchar(255), size varchar(255), maxsize varchar(255), growth varchar(255), usage varchar(255) ); insert into #temp select * FROM OPENROWSET("SQLNCLI", "SERVER=****;UID=****;PWD=****", " exec sp_foreachdb @command="" Exec ?..sp_helpfile;"" WITH RESULT SETS ((name varchar(255), field varchar(255), filename varchar(255), filegroup varchar(255), size varchar(255), maxsize varchar(255), growth varchar(255), usage varchar(255))); ") select * from #temp 

w lekérdezés felett ill csak az sp_foreachdb végrehajtás első eredményhalmazát adja vissza. de az alábbi lekérdezés egyetlen adatbázisban adja vissza az összes adatbázis eredményét.

create table #temp ( name varchar(255), field varchar(255), filename varchar(255), filegroup varchar(255), size varchar(255), maxsize varchar(255), growth varchar(255), usage varchar(255) ); exec sp_foreachdb @command="INSERT INTO #temp Exec ?..sp_helpfile;" select * from #temp 

Válasz

Megpróbálhatja Aaron SP alkalmazkodását megszabadulással dinamikus része. A dinamikus rész állítólag felépít egy lekérdezést, amely csak az sys.databases adatbázis neveit olvassa el a megadott argumentumok alapján. A dinamikus SQL-t a lekérdezés leghatékonyabbá tételére választják – Figyelembe véve sajátos igényeit, bizonyos áldozatok rendben lehetnek.

Ugyanakkor azt állítom, hogy az előadás nem sokat szenvedhet az alább felajánlott átírás miatt, mivel a sys.databases rendszer nézetben általában nincs túl sok sor, de mindenképpen felveheti a OPTION (RECOMPILE) -t. Bármilyen lassú is, bár valószínűleg meglehetősen csúnya lesz a vége, amit ígérhetek.

Az átírás módszere a következő: Aaron eljárása egy ismétlődő minta felhasználásával építi fel a lekérdezést, ahol egy paraméter értékét ellenőrzik, , az eredmény alapján további lekérdezés hozzáadódik a dinamikus lekérdezéshez, például a következőképpen:

SET @sql = N"SELECT name FROM sys.databases WHERE 1=1" + CASE WHEN some_condition1 THEN "AND some_filter1" ELSE "" END + CASE WHEN some_condition2 THEN "AND some_filter2" ELSE "" END + ... 

Így írhatja át:

SELECT name FROM sys.databases WHERE 1=1 AND (some_filter1 OR opposite_of_some_condition1) AND (some_filter2 OR opposite_of_some_condition2) AND ... OPTION (RECOMPILE); 

Például a @system_only szabályozza, hogy a database_id IN (1,2,3,4) szűrőt be kell-e venni, például:

SET @sql = N"SELECT name FROM sys.databases WHERE 1=1" + CASE WHEN @system_only = 1 THEN " AND database_id IN (1,2,3,4)" ELSE "" END 

Az átírt lekérdezés a következő módon kerül paraméterezésre:

SELECT name FROM sys.databases WHERE 1=1 AND (database_id IN (1,2,3,4) OR @system_only <> 1) -- or: @system_only = 0 

A kapott lekérdezést használja közvetlenül a kurzort a

 SELECT CASE WHEN @suppress_quotename = 1 THEN db ELSE QUOTENAME(db) END FROM #x ORDER BY db 

helyett, mint látható, az utolsó érintésre a SELECT részre kell menni, ahol az egyszerű helyébe a következő lép:

 SELECT CASE WHEN @suppress_quotename = 1 THEN name ELSE QUOTENAME(name) END 

Nyilvánvaló, hogy most már megszabadulhat a #x tábla, amire már nincs szükség az SP-ben.

Egy utolsó megjegyzés az adott adatbázishoz tervezett futtatásra vonatkozik.

@command1="use ?; Exec sp_helpfile;" 

helyett csak

@command1="Exec ?..sp_helpfile;" 

válasz

Cserét írtam, amelynek számos fejlesztése van az eredeti sp_foreachdb , beleértve a fészkelés képességét. Az újabb, előnyben részesített eljárást sp_ineachdb ( 1. rész / 2. rész ), és a Brent Ozar “s első válaszkészlet részeként is elérhető.

Néhány háttér itt :

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük