À l'aide de la fonction OPENROWSET pour récupérer dynamiquement SP résultats lorsque SP contient # temp tables
Mon Scénario
Je suis en train de travailler sur une base de données qui va contenir beaucoup de détails à partir de différentes Procédures Stockées dans différentes bases de données à travers l'ensemble du serveur. Les informations que j'essaie de rassembler est maintenant, "Quel est le SP de sortie?"
Dans la recherche j'ai trouvé que la réponse se trouve dans OPENROWSET. Mon premier essai a été un succès et tout avait l'air super. Cependant, lors d'un test live SPs j'ai rencontré un problème majeur: Elle ne joue pas bien avec le temp (#) des tables.
Par exemple:
Si je devais prendre cette SP:
CREATE PROCEDURE dbo.zzTempSP(@A INT, @B INT) AS
SELECT @A AS A, @B AS B
Je peux facilement insérer le résultat dans un temp (##) tableau avec le code suivant, puis de requête de la base de données tempdb est sysobjects et de produire une liste de colonnes et de leurs types de données:
IF OBJECT_ID('tempdb.dbo.##TempOutput','U') IS NOT NULL DROP TABLE ##TempOutput
DECLARE @sql VARCHAR(MAX)
SELECT @sql = 'SELECT *
INTO ##TempOutput
FROM OPENROWSET(''SQLNCLI'', ''Server=' +
CONVERT(VARCHAR(100), SERVERPROPERTY('MachineName')) +
';Trusted_Connection=yes;'', ''SET FMTONLY OFF exec ' +
DB_NAME() +
'.dbo.zzTempSP @A=1, @B=2'')'
EXEC(@sql)
SELECT *
FROM ##TempOutput
Grand! Toutefois, si le SP a été plutôt ceci:
CREATE PROCEDURE dbo.zzTempSP (@A INT, @B INT) AS CREATE TABLE dbo.#T (A INT, B INT)
INSERT INTO dbo.#T
SELECT @A AS A, @B AS B
SELECT *
FROM dbo.#T
Lorsque j'exécute la même OPENROWSET
code comme avant j'ai l'erreur suivante:
Ne peut pas traiter l'objet "FMTONLY SET OFF exec DatabaseName.dbo.zzTempSP @A=1,@B=2". Le fournisseur OLE DB "SQLNCLI10" du serveur lié "(null)" indique que l'objet n'a pas de colonnes ou de l'utilisateur actuel ne dispose pas des autorisations sur l'objet.
Quand j'ai couper vers le bas la fonction OPENROWSET code (par la suppression de la dynamique des trucs):
SELECT *
FROM OPENROWSET('SQLNCLI','Server=ServerName;Trusted_Connection=yes;',
'exec DatabaseName.dbo.zzTempSP @A=1,@B=2'
)
J'ai le message suivant (beaucoup plus utile d'erreur:
Nom d'objet non valide '#T'.
Qui est l'endroit où j'ai frappé le mur. Dans mes recherches, il semble qu'il n'y a pas de solution, mais je ne pouvais pas me résoudre à abandonner tout de suite.
Et donc, je suis conduit à..
Ma question pour vous
Quelqu'un est-il au courant de toute façon possible de contourner cette erreur? Ou est-il éventuellement une solution alternative?
Ce processus ne sera pas souvent donc je n'ai pas besoin de trop se soucier de la solution de l'efficacité.
Toute entrée serait grandement apprécié.
Grâce,
Zok
PS: Désolé pour la mise en forme. Je n'ai pas tout à fait comprendre les balises de langue.
Dans le même plomb je l'ai mentionné ci-dessus, ils ont dû introduire un No-Op à la SP. J'ai envisagé la création d'une procédure intermédiaire qui permettrait d'analyser la SP, nous tentons de recueillir des détails à partir de (par syscomments) en tirant sur la définition de la table temporaire pour créer dynamiquement un Pas Op, mais je vois beaucoup de problèmes qui pourraient être difficiles à contourner. Donc, je suis toujours dans le même bateau.
Génial les efforts mis en place par vous....merci
OriginalL'auteur Zok Wobblefotz | 2011-10-19
Vous devez vous connecter pour publier un commentaire.
J'ai eu cette question posté sur SQL Server Centrale ainsi et que certaines réponses m'a mis dos à la recherche d'une réponse à l'intérieur de la fonction OPENROWSET (et de trouver). L'une des personnes m'a mis à cet article's la section sur OPENQUERY. Il affirme que pour contourner le problème avec des tables temporaires vous suffit d'ajouter FMTONLY SET OFF à l'exécution de la ligne de votre OPENQUERY/OPENROWSET énoncé comme suit:
Toutefois, si la procédure n'a pas de SET NOCOUNT on spécifiée, il soulève encore une erreur.
J'ai eu un stupide malentendu à propos de SET NOCOUNT on dans l'arrière de ma tête qui m'empêchait de penser, "Hé, je ne peux pas juste ajouter SET NOCOUNT on à l'instruction d'exécution de la fonction OPENROWSET??" Une fois que quelqu'un pose cette question pour moi sur l'autre fil, il fait trop beaucoup de sens =) Alors, voici la solution que j'ai été cherché:
Je tiens à avertir les utilisateurs de l'utilisation de 'FMTONLY SET OFF" dans tous les cas critiques: n'oubliez pas, le réglage du FMTONLY SET OFF' provoque une DOUBLE exécution en cours des états! Si votre SP insère des données, vous pouvez avoir des ennuis! Avec FMTONLY DÉSACTIVÉ l'option SQL Server de l'instruction de la requête premier metdata.
OriginalL'auteur Zok Wobblefotz
D'accord.. j'ai abandonné et repris mon vieil ami xpcmdshell. Tout au long de cette réponse et son code le trait de soulignement (_) est implicite, pour xpcmdshell comme souvent, je ne peux pas charger les pages contenant le nom complet.
Tout d'abord, voici trois choses que j'ai essayé ça ne fonctionne PAS (je ne me souviens pas de tous les autres):
Et donc, après beaucoup de tête dénigrement et la recherche sur Google, je suis tombé en arrière pour xpcmdshell. Le script suivant (que je vais avoir dans une procédure) prend un SP instruction exec et la base de données pour l'exécuter en vertu de l', formats un xpcmdshell sqlquery de commande dans un fichier, exécute le fichier et insère la sortie de celui-ci dans une table temporaire, puis extrait les en-têtes de colonne de ces résultats dans une autre table temp.
Si vous prévoyez d'utiliser ce code, n'oubliez pas de faire un rechercher remplacer pour xpcmdshell à xp(_)cmdshell
Espère que cela aide quelqu'un! S'il vous plaît n'hésitez pas à poster des questions, des commentaires ou des suggestions que vous pourriez avoir.
OriginalL'auteur Zok Wobblefotz
Vous utilisez une table Temp variable #T. Vous devez utiliser une table Temporaire @T.
Selon ma compréhension, la table temporaire variable ne peut pas être utilisé dans les transactions distribuées environnement et aussi que vous pourriez ne pas avoir accès à la base de données TempDB dans le serveur lié.
OriginalL'auteur Vivek Rawat