Essayer de créer une requête dynamic volumineuse ne cesse de se tronquer

J'ai une requête SQL dans le server SQL où j'essaye de créer une grande requête avec 'union' sur un grand nombre de bases de données. Toutefois, la requête continue à être tronquée. D'après mes searchs, cela ne devrait pas arriver si tous les varchar sont castés en varchar(MAX) . J'ai essayé de le faire, cependant, il est toujours tronqué. La requête finale doit être dans la @finalQuery @finalQuery. Quelqu'un peut-il aider avec la requête ci-dessous?

 DECLARE @name VARCHAR(MAX) -- database name DECLARE @path VARCHAR(MAX) -- path for backup files DECLARE @fileName VARCHAR(MAX) -- filename for backup DECLARE @fileDate VARCHAR(MAX) -- used for file name DECLARE @executeQuery VARCHAR(MAX) DECLARE @finalQuery VARCHAR(MAX) SET @finalQuery = '' DECLARE db_cursor CURSOR FOR SELECT name FROM master..sysdatabases WHERE name NOT IN (CAST('master' AS VARCHAR(MAX)),CAST('model' AS VARCHAR(MAX)),CAST('msdb' AS VARCHAR(MAX)),CAST('tempdb' AS VARCHAR(MAX))) OPEN db_cursor FETCH NEXT FROM db_cursor INTO @name WHILE @@FETCH_STATUS = 0 BEGIN SET @executeQuery=CAST( 'SELECT TOP 1000 [EmailAddress] as ''Email Address'' ,[FirstName] as ''First Name'' ,[LastName] as ''Last Name'' ,[LastLogin] as ''Last Login'', Name as ''User Role'' FROM '+@name+'.[dbo].[User] c INNER JOIN ( SELECT * FROM '+@name+'.[dbo].[SecurityRole] as a INNER JOIN '+@name+'.[dbo].[SecurityRoleToUser] as b ON (a.ID=b.SecurityRoleID) ) d ON (c.ID=d.UserID) WHERE IsActive=1' AS VARCHAR(MAX)) --PRINT @executeQuery --PRINT @name --PRINT @executeQuery SET @finalQuery = CAST(@executeQuery+' UNION ALL ' +@finalQuery AS VARCHAR(MAX)) --PRINT @executeQUery --EXEC (@executeQuery) FETCH NEXT FROM db_cursor INTO @name END CLOSE db_cursor DEALLOCATE db_cursor PRINT @finalQuery --EXEC(@finalQuery) 

Vous feriez mieux de ne pas faire UNION travers autant de bases de données. Et tu n'en as pas besoin. En outre, les noms de bases de données, etc sont tous sysname qui équivaut à NVARCHAR(128) donc préférable d'utiliser NVARCHAR(MAX) au lieu de VARCHAR(MAX) .

Étape 1: Génération de requêtes less complexe

 DECLARE @DatabaseName sysname; DECLARE @Query NVARCHAR(MAX), @Template NVARCHAR(MAX); SET @Query = ''; SET @Template = N'USE [?]; SELECT TOP 1000 [EmailAddress] as [Email Address] ,[FirstName] as [First Name] ,[LastName] as [Last Name] ,[LastLogin] as [Last Login], Name as [User Role] FROM [dbo].[User] c INNER JOIN ( SELECT * FROM [dbo].[SecurityRole] as a INNER JOIN [dbo].[SecurityRoleToUser] as b ON (a.ID=b.SecurityRoleID) ) d ON (c.ID=d.UserID) WHERE IsActive = 1; '; SELECT @Query = (@Query + REPLACE(@Template, N'?', sd.[name])) FROM sys.databases sd WHERE sd.[name] NOT IN (N'master', N'model', N'msdb', N'tempdb') AND HAS_DBACCESS(sd.[name]) = 1; --EXEC(@Query); -- uncomment when not debugging SELECT LEN(@Query); -- 9506 on my system -- comment out if debugging print @query; -- truncates at 4000 chars for NVARCHAR -- comment out if debugging 

Étape 2: Pas besoin d'UNION

Au lieu d'utiliser UNION pour get tout dans un set de résultats unique, il suffit d'insert plusieurs sets de résultats dans une table temporaire locale.

 CREATE TABLE #tmp (DatabaseName sysname NOT NULL, EmailAddress NVARCHAR(200), FirstName NVARCHAR(50), LastName NVARCHAR(50), LastLogin DATETIME, UserRole VARCHAR(50); DECLARE @Query NVARCHAR(MAX), @Template NVARCHAR(MAX); SET @Query = ''; SET @Template = N'USE [?]; SELECT TOP 1000 DB_NAME() AS [DatabaseName], [EmailAddress] as [Email Address] ,[FirstName] as [First Name] ,[LastName] as [Last Name] ,[LastLogin] as [Last Login], Name as [User Role] FROM [dbo].[User] c INNER JOIN ( SELECT UserID, Name--* -- see Step #3 below FROM [dbo].[SecurityRole] sr INNER JOIN [dbo].[SecurityRoleToUser] srtu ON sr.ID = srtu.SecurityRoleID ) d ON c.ID = d.UserID WHERE IsActive = 1; '; SELECT @Query = (@Query + REPLACE(@Template, N'?', sd.[name])) FROM sys.databases sd WHERE sd.[name] NOT IN (N'master', N'model', N'msdb', N'tempdb') AND HAS_DBACCESS(sd.[name]) = 1; INSERT INTO #tmp (DatabaseName, EmailAddress, FirstName, LastName, LastLogin, UserRole) EXEC(@Query); SELECT * FROM #tmp; 

Étape 3:

Il est préférable de ne pas utiliser SELECT * dans votre SELECT * FROM [dbo].[SecurityRole] as a sous SELECT * FROM [dbo].[SecurityRole] as a requête. Sélectionnez simplement les champs dont vous avez besoin, car il est plus probable que vous utilisiez des index. Il semble que vous ayez juste besoin de deux champs: UserID, Name

C'est PRINT qui est tronqué, pas votre variable:

À partir des documents sur PRINT :

Une string de message peut contenir jusqu'à 8 000 caractères s'il s'agit d'une string non-Unicode et 4 000 caractères s'il s'agit d'une string Unicode. Les strings plus longues sont tronquées. Les types de données varchar(max) et nvarchar(max) sont tronqués en types de données qui ne sont pas plus grands que varchar(8000) et nvarchar(4000) .

Pourquoi utiliser un slider?

 SELECT 'SELECT TOP 1000 [EmailAddress] as ''Email Address'' ,[FirstName] as ''First Name'' ,[LastName] as ''Last Name'' ,[LastLogin] as ''Last Login'', Name as ''User Role'' FROM ' + name + '.[dbo].[User] c' ..... FROM master..sysdatabases WHERE name NOT IN (CAST('master' AS VARCHAR(MAX)),CAST('model' AS VARCHAR(MAX)),CAST('msdb' AS VARCHAR(MAX)),CAST('tempdb' AS VARCHAR(MAX)))