Sql-Server

格式化 SSMS 輸出中的列長度

  • March 24, 2019

SQL Server 2012。本文底部的範例查詢。

我正在嘗試為上次備份給定數據庫的時間創建一個簡單的報告。

在 SSMS 中執行範例查詢並輸出到文本DB_NAME時,該列被格式化為數據的最大可能大小(DB2 中存在同樣的問題,順便說一句)。所以,我有一列包含不超過 12 個字元的數據,但它儲存在 avarchar(128)中,無論如何我都會得到 128 個字元的數據。RTRIM對輸出沒有影響。

您是否知道一種優雅的方法可以使格式化的列長度成為實際數據的最大大小,而不是數據的最大潛在大小?

我想存在一個xp_sprintf()函式,但我不熟悉它,而且它看起來不是非常健壯。

我試過這樣投射它:

DECLARE @Servername_Length int;
SELECT  @Servername_Length =        LEN(    CAST(   SERVERPROPERTY('Servername') AS VARCHAR(MAX)    )   ) ;

...
SELECT  
  CONVERT(CHAR(@Servername_Length), SERVERPROPERTY('Servername')) AS Server, 
...

但是 SQL Server 不允許我在轉換時使用定義中的@database_name_Length變數varchar。顯然,SQL Server 在聲明charorvarchar變數時需要一個文字數字。

我決定在字元串中建構語句並使用類似的東西sp_executesql,或者建構一個具有我需要的實際列長度的臨時表,這兩者都比我希望去的麻煩多一點,只是為了不得到 100我的輸出中的空格在 128 個字元的列上。

搜尋了網際網路並找到了bupkus。

也許我在尋找錯誤的東西,或者Google對我有意見。

SSMS 似乎會將列格式化為允許的最大大小,即使實際數據要小得多。我希望有一種優雅的方式來“解決”這個問題,而無需跳過箍。我正在使用 SSMS 2012。

如果我轉到結果到網格,然後轉到 Excel 或類似的東西,尾隨空格將被消除。不過,我希望基本上可以創建一份我通過電子郵件發送的報告。

範例查詢

--------------------------------------------------------------------------
QUERY:
--------------------------------------------------------------------------
SELECT  
  CONVERT(CHAR(32), SERVERPROPERTY('Servername')) AS Server, 
  '''' + msdb.dbo.backupset.database_name + '''',  
  MAX(msdb.dbo.backupset.backup_finish_date) AS last_db_backup_date 
FROM   msdb.dbo.backupmediafamily  
  INNER JOIN msdb.dbo.backupset ON msdb.dbo.backupmediafamily.media_set_id = msdb.dbo.backupset.media_set_id  
WHERE  msdb..backupset.type = 'D' 
GROUP BY 
  msdb.dbo.backupset.database_name  
ORDER BY  
  msdb.dbo.backupset.database_name 

CONVERT(VARCHAR(xx), ColumnName)如果您希望列在文本輸出視圖中顯得更短,則需要在所有列上使用。

將您的查詢轉換為:

SELECT [Server] = CONVERT(VARCHAR(30), SERVERPROPERTY('Servername')) 
  , DatabaseName = CONVERT(VARCHAR(30), '''' + bs.database_name + '''')
  , LastDatabaseBackupDate = CONVERT(VARCHAR(30), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
   INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = 'D' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;

這將提供類似於以下內容的輸出:

Server                         DatabaseName                   LastDatabaseBackupDate
------------------------------ ------------------------------ ------------------------------
[ServerName]                   'A'                            Sep 25 2015 11:32AM
[ServerName]                   'B'                            Apr 21 2015 12:09PM
[ServerName]                   'C'                            Feb 24 2015  9:16PM
[ServerName]                   'D'                            Oct  8 2014 11:02AM
[ServerName]                   'E'                            May 14 2014  6:27PM

(5 row(s) affected)

如果您希望能夠在不修改 T-SQL 程式碼的情況下動態更改列寬,則需要使用 Dynamic SQL:

DECLARE @ColumnWidth VARCHAR(4);
DECLARE @Cmd NVARCHAR(MAX);

SET @ColumnWidth = '24';
SET @Cmd = '
SELECT [Server] = CONVERT(VARCHAR(' + @ColumnWidth + '), SERVERPROPERTY(''Servername'')) 
  , DatabaseName = CONVERT(VARCHAR(' + @ColumnWidth + '), '''''''' + bs.database_name + '''''''')
  , LastDatabaseBackupDate = CONVERT(VARCHAR(' + @ColumnWidth + '), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
   INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = ''D'' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;
';

EXEC (@cmd);

在這裡,我將所有列的寬度設置為 24,它看起來像:

Server                   DatabaseName             LastDatabaseBackupDate
------------------------ ------------------------ ------------------------
SERVERNAME               'A'                      Sep 25 2015 11:32AM
SERVERNAME               'A'                      Apr 21 2015 12:09PM
SERVERNAME               'A'                      Feb 24 2015  9:16PM
SERVERNAME               'A'                      Oct  8 2014 11:02AM
SERVERNAME               'A'                      May 14 2014  6:27PM

(5 row(s) affected)

如果您真的想發瘋並讓列自動調整大小,您可以這樣做:

DECLARE @ColumnWidthServer VARCHAR(4);
DECLARE @ColumnWidthDatabase VARCHAR(4);
DECLARE @ColumnWidthLastBackup VARCHAR(4);

DECLARE @Cmd NVARCHAR(MAX);

SELECT @ColumnWidthServer = 1 + LEN(CONVERT(VARCHAR(128), SERVERPROPERTY('Servername')))
  , @ColumnWidthDatabase = 1 + MAX(LEN('''' + bs.database_name + ''''))
  , @ColumnWidthLastBackup = 1 + MAX(LEN(CONVERT(VARCHAR(128), bs.backup_finish_date)))
FROM msdb.dbo.backupmediafamily  bmf
   INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = 'D';

SET @Cmd = '
SELECT [Server] = CONVERT(VARCHAR(' + @ColumnWidthServer + '), SERVERPROPERTY(''Servername'')) 
  , DatabaseName = CONVERT(VARCHAR(' + @ColumnWidthDatabase + '), '''''''' + bs.database_name + '''''''')
  , LastDatabaseBackupDate = CONVERT(VARCHAR(' + @ColumnWidthLastBackup + '), MAX(bs.backup_finish_date))
FROM msdb.dbo.backupmediafamily  bmf
   INNER JOIN msdb.dbo.backupset bs ON bmf.media_set_id = bs.media_set_id  
WHERE  bs.[type] = ''D'' 
GROUP BY bs.database_name  
ORDER BY bs.database_name;
';

EXEC (@cmd);

引用自:https://dba.stackexchange.com/questions/117484