Comment exécuter une longue requête dynamic (plus de 4000 caractères) – à nouveau

Note: Je cours sous SQL Server 2008 R2 …

J'ai pris le time de lire des dizaines de messages sur ce site et d'autres sites sur la façon d'exécuter SQL dynamic où la requête est de plus de 4000 caractères. J'ai essayé plus d'une douzaine de solutions proposées. Le consensus semble être de split la requête en variables de 4000 caractères, puis faire:

EXEC (@SQLQuery1 + @SQLQuery2) 

Cela ne fonctionne pas pour moi – la requête est tronquée à la fin de @ SQLQuery1.

Maintenant, j'ai vu des exemples comment les gens "forcent" une longue requête en utilisant REPLICATE un tas d'espaces, etc., mais c'est une vraie requête – mais il devient un peu plus sophistiqué que cela.

J'ai SQL View avec un nom de "Company_A_ItemView".

J'ai 10 entresockets que je veux créer la même vue exacte, avec des noms différents, par exemple "Company_B_ItemView" "Company_C_ItemView" ..etc.

Si vous offrez de l'aide, ne requestz pas pourquoi il y a plusieurs vues – acceptez simplement que je dois le faire de cette façon, OK?

Chaque entreprise possède son propre set de tables et l'instruction CREATE VIEW reference plusieurs tables par nom. Voici un exemple BREVE, mais n'oubliez pas que la longueur totale de la requête est d'environ 6000 caractères:

 CREATE view [dbo].[Company_A_ItemView] as select WE.[Item No_], WE.[Location Code], LOC.[Bin Number], [..more fields, etc.] from [Company_A_Warehouse_Entry] WE left join [Company_A_Location] LOC 

…vous avez eu l'idée

Donc, ce que je fais actuellement est:

une. Extraction du contenu de l'instruction CREATE VIEW dans 2 variables déclarées, par exemple

 Set @SQLQuery1 = (select text from syscomments where ID = 1382894081 and colid = 1) Set @SQLQuery2 = (select from syscomments where ID = 1382894081 and colid = 2) 

Notez que c'est ainsi que SQL stocke les définitions longues – lorsque vous créez la vue, il stocke le text dans plusieurs loggings syscomments. Dans mon cas, la vue est divisée en un bloc de text de 3591 caractères dans le premier logging syscomment et le rest du text est dans le deuxième logging. Je ne sais pas pourquoi SQL n'utilise pas tous les 4000 caractères dans le champ syscomment. Et la déclaration est brisée au milieu d'un mot.

Veuillez noter dans tous mes exemples que toutes les variables @SQLQueryxxx sont déclarées comme varchar (max). J'ai également essayé de les déclarer comme nvarchar (max) et varchar (8000) et nvarchar (8000) avec les mêmes résultats.

b. Je fais ensuite un "Search and Replace" pour "Company_A" et le remplace par "Company_B". Dans le code ci-dessous, la variable "@CompanyID" est d'abord définie sur "Company_B":

 SET @SQLQueryNew1 = @SQLQuery1 SET @SQLQueryNew1 = REPLACE(@SQLQueryNew1, 'Company_A', @CompanyID) SET @SQLQueryNew2 = @SQLQuery2 SET @SQLQueryNew2 = REPLACE(@SQLQueryNew2, 'Company_A',@CompanyID) 

c. J'essaie ensuite:

 EXEC (@SQLQueryNew1 + @SQLQueryNew2) 

Le message renvoyé indique qu'il essaie d'exécuter l'instruction tronquée à la fin de @ SQLQueryNew1, par exemple, 80% (environ) du text de la requête.

J'ai essayé CAST'ing le résultat final dans un nouveau varchar (max) et nvarchar (max) – pas de chance j'ai essayé CAST'ing la requête originale un nouveau varchar (max) et nvarchar (max) – pas de chance

J'ai regardé le résultat de la récupération de l'instruction CREATE VIEW d'origine, et ça va.

J'ai essayé plusieurs autres façons de récupérer l'instruction CREATE VIEW d'origine, comme:

 Set @SQLQuery1 = (select VIEW_DEFINITION) FROM [MY_DATABASE].[INFORMATION_SCHEMA].[VIEWS] where TABLE_NAME = 'Company_A_ItemView')` 

Celui-ci renvoie uniquement les 4000 premiers caractères de la vue CREATE

 Set @SQLQuery1 = (SELECT (OBJECT_DEFINITION(@ObjectID)) 

Si je fais un

 SELECT LEN(OBJECT_DEFINITION(@ObjectID)) 

il returnne la bonne longueur de la requête (par exemple 5191), mais si je regarde @ SQLQuery1, ou essaie de

 EXEC(@SQLQuery1), the statement is still truncated. 

c. Il y a quelques references qui indiquent que puisque je manipule le text de la question après l'avoir récupéré, les variables résultantes sont alors tronquées à 4000 caractères. J'ai essayé de CAST'ing le résultat comme je fais le REMPLACEMENT, par exemple

 SET @SQLQueryNew1 = SELECT (CAST(REPLACE(@SQLQueryNew1, 'Company_A', @CompanyID) AS varchar(max)) 

Même résultat

Je sais qu'il existe d'autres methods, telles que la création de procédures stockées pour créer les vues. Mais les vues sont en cours de développement et sont quelque peu "en stream", donc placer le text de CREATE VIEW à l'intérieur d'un proc stocké est fastidieux. Mon but est de pouvoir prendre la vue de Company_A et de la répliquer exactement – plusieurs fois, sauf le nom de la vue et les noms de table de Company_B, le nom de la vue et les noms de table de Company_C, etc.

Je me request s'il y a quelqu'un là-bas qui a fait ce type de manipulation d'une longue instruction SQL "CREATE VIEW" et essaie de l'exécuter.

Utilisez simplement VARCHAR (MAX) ou NVARCHAR (MAX) . Ils fonctionnent bien pour EXEC (ssortingng) .


FYI,

Notez que c'est ainsi que SQL stocke les définitions longues – lorsque vous créez la vue, il stocke le text dans plusieurs loggings syscomments.

Ce n'est pas correct. C'est ainsi que cela a été fait sur SQL Server 2000. Depuis SQL Server 2005 et supérieur, ils sont enregistrés en tant que NVARCHAR (MAX) dans une seule input dans sys.sql_modules .

syscomments est toujours disponible, mais il est conservé en lecture seule uniquement pour des raisons de compatibilité.


Donc, tout ce que vous devez faire est de changer votre @ SQLQuery1,2, etc. variables à une seule variable NVARCHAR (MAX) et tirez plutôt votre code View de la colonne [definition] de la table sys.sql_modules.

Notez que vous devez faire attention à vos manipulations de strings car certaines fonctions returnneront à la sortie (N) VARCHAR (4000) si tous leurs arguments d'input ne sont pas (N) VARCHAR (MAX). (Désolé, je ne sais pas lesquels, mais REPLACE () peut en être un). En fait, c'est peut-être ce qui a causé tant de confusion dans vos tests.

déclarez vos variables sql (@ SQLQuery1 …) comme nvarchar(4000) assurez-vous que chaque partie sql ne dépasse pas 4000 octets (copyz chaque partie dans un file text et testez la taille du file en octets)