以下は、sqlcmd
でクエリを実行したときに現在取得しているものです。
1> SELECT 1,2,3,4
2> GO
----------- ----------- ----------- -----------
1 2 3 4
(1 rows affected)
より長い結果の場合、この出力フォーマットは人間が読める形式ではありませんが、ターミナルでラップされるためです。
結果を垂直に表示するにはどうすればよいですか( \G
in mysql
)?または人間が読める別の方法で?
SELECT F1, F2, F2
を使用した場合の期待される結果は、SELECT文の各フィールドに対して1つの列を取得することです。
SELECT '1' + CHAR(13) + '2' + CHAR(13) + '3' + CHAR(13)
------
1
2
3
(1 row(s) affected)
UNIONを使用できます。
select 1 union select 2 union select 3 union select 4
結果:
-----------
1
2
3
4
(4 rows affected)
結果ウィンドウに結果を垂直に表示する への純粋なT-SQLアプローチを見つけました。これには、このリンクからコピーしているカスタムストアドプロシージャ(sp_SHOWDOWN)が含まれます。あなたはそれで遊んで、それが役立つかどうかを確認することができます。
著者はいくつかの制限を示しています:
ここに簡単な説明があります(投稿から引用):
この手順を使用すると、画面全体ではなく垂直方向(下)に結果を表示できます。 50列と2、3レコードしかないクエリを処理する場合に最適です。
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
/********************************************************************************************************
** NAME: sp_ShowDown
**
** DESC: Display (SHOWs) the results of a SELECT vertically (DOWN) instead of horizontally
** The query can be as complex as necessary with as many joins however the column names
** must be unique because of the temp table. Note image and text fields display only
** their size (DATALENGTH)
**
** PARM: @Help = 1 will display syntax and instructions
**
** RETR: the resultset of the records. Notes displaying a lot of records will take a LONG time. Generally
** this should be used for recordsets of no more than 10.
**
** AUTH: D. Simmons
**
** SYNTAX sp_showdown 1 -- displays full syntax on how to run
**
** MOD DATE:
** 05.22.07 - DTS Prevent casting of image & text to varchar
** 05.20.07 - DTS original version
*********************************************************************************************************/
ALTER PROCEDURE [dbo].[sp_ShowDown] (
@help BIT = NULL
)
AS
SET NOCOUNT ON
-- ------------------------------------------------------------------------
-- DECLARATION AND TABLE CREATION
-- ------------------------------------------------------------------------
DECLARE
@Column VARCHAR(60), -- the fieldname
@CurrOrdPos INT, -- the order of the column in the table
@SQL VARCHAR(1000), -- dynamic select statement
@SQ CHAR(1), -- single quote
@MaxTable VARCHAR(1000), -- holds the tempwide2 name - the true one stored in tempdb
@RecordID INT, -- each record's number to aid in sorting when more than one record is return
@DataType VARCHAR(25), -- the datatype of the field
@FieldName VARCHAR(200) -- will hold column's name with brackets ready for the SELECT
IF OBJECT_ID('tempdb..#tempdown') IS NOT NULL DROP TABLE #tempdown
CREATE TABLE #tempdown (
Rec INT, -- short column names on purpose so it doesn't take up much
Ord INT, -- space in final result
ColumnName VARCHAR(60), -- the columnname
Data VARCHAR(7500) -- the data for the column
)
-- ------------------------------------------------------------------------
-- INITIALIZE
-- ------------------------------------------------------------------------
SET @RecordID = 0
-- CONSTANTS
SET @SQ = CHAR(39) -- single quote
-- ------------------------------------------------------------------------
-- LOGIC
-- ------------------------------------------------------------------------
-- print the syntax and usage instructions to the result window
IF @Help = 1 BEGIN
PRINT 'Keep in mind that with temp tables the column names must be unique!'
PRINT ' '
PRINT 'Example of syntax: '
PRINT ' '
PRINT 'IF OBJECT_ID(''tempdb..#tempwide'') IS NOT NULL DROP TABLE #tempwide -- ADD TO TOP OF YOUR SELECT'
PRINT ' '
PRINT 'SELECT TOP 1 * '
PRINT 'INTO #tempwide -- ADD THIS TO YOUR QUERY'
PRINT 'FROM authors a'
PRINT ' '
PRINT 'EXEC _SHOWDOWN -- ADD AS THE LAST LINE'
PRINT ' '
PRINT 'COPY THESE LINES and place where instructed'
PRINT 'IF OBJECT_ID(''tempdb..#tempwide'') IS NOT NULL DROP TABLE #tempwide'
PRINT 'INTO #tempwide'
PRINT 'EXEC sp_SHOWDOWN'
RETURN
END
-- Create a new 'wide' table so we can add a RecordID (DIDROCER) which allows muliple records and their fields
-- to be grouped together. DIDROCER is RecordID backwards. Needed a field name that will have an unlikely
-- chance of ever being in a real table since it will be excluded from the results displayed vertically.
SELECT 0 'DIDROCER', *
INTO #tempwide2
FROM #tempwide
-- increment the record id for the table
UPDATE #tempwide2 SET @RecordID = DIDROCER = @RecordID + 1
-- get name of tempwide2 table (the true name in tempdb)
SET @MaxTable = ( SELECT MAX(TABLE_NAME)
FROM tempdb.INFORMATION_SCHEMA.TABLES
WHERE Table_Name LIKE '%#tempwide2%'
)
-- get the min ord position for the first column for my temp table. Eliminates need for cursor
SET @CurrOrdPos = ( SELECT MIN(Ordinal_Position)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE Table_Name LIKE '%' + @MaxTable + '%' )
-- while we have columns in the temp table loop through them and put their data into the
-- tempdown table
WHILE @CurrOrdPos IS NOT NULL BEGIN
-- get a column name and the data type
SELECT @Column = COLUMN_NAME, @DataType = Data_Type
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE Table_Name LIKE '%' + @MaxTable + '%'
AND Ordinal_Position = @CurrOrdPos
IF @Column <> 'DIDROCER' BEGIN -- if it is not the recordid (spelled backward) row from tempwide2 get the row
IF @DataType IN ( 'image', 'text' ) BEGIN
-- 'Size of Data: ' + CONVERT(VARCHAR(15), DATALENGTH([NoteText] ))
SET @FieldName = @SQ + 'Size of Data: ' + @SQ + ' + CONVERT(VARCHAR(15), DATALENGTH(' + @FieldName + ')) '
END ELSE BEGIN
SET @FieldName = 'CAST( [' + @Column + '] AS VARCHAR(7500) )' -- the fieldname w/ brackets used in SELECT to display the data
END
-- build the insert that will put the data into the tempdown table
SET @SQL = ' INSERT INTO #tempdown '
SET @SQL = @SQL + 'SELECT didrocer ' + @SQ + 'RecordID' + @SQ + ', ' -- recordid field from tempwide2 table
SET @SQL = @SQL + CONVERT(VARCHAR(10), @CurrOrdPos) + ', ' -- order of the column
SET @SQL = @SQL + @SQ + @Column + @SQ + ' ' + @SQ + 'Field' + @SQ + ', ' -- field name
SET @SQL = @SQL + @FieldName + @SQ + @Column + @SQ -- field data
SET @SQL = @SQL + ' FROM ' + @MaxTable -- from tempwide2
END
--@SQL above looks like this:
--INSERT INTO #tempdown SELECT DIDROCER 'RecordID', 5, 'UserID' 'Field', [UserID] 'UserID' FROM #tempwide2 {shorten}_____00010000003F
--PRINT @SQL
EXEC ( @SQL ) -- run the insert into #tempdown
-- get the next column pos
SET @CurrOrdPos = ( SELECT MIN(Ordinal_Position)
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE Table_Name LIKE '%' + @MaxTable + '%'
AND Ordinal_Position > @CurrOrdPos)
END
-- display the results VERTICALLY!
SELECT ColumnName, Data FROM #tempdown ORDER BY Rec, Ord, ColumnName
-- clean up
IF OBJECT_ID('tempdb..#tempdown') IS NOT NULL DROP TABLE #tempdown
IF OBJECT_ID('tempdb..#tempwide') IS NOT NULL DROP TABLE #tempwide
IF OBJECT_ID('tempdb..#tempwide2') IS NOT NULL DROP TABLE #tempwide2
データのテストベッドのセットアップ
--Setup testbed of data
DROP TABLE IF EXISTS dbo.customer
CREATE TABLE [dbo].[Customer] (
[CustomerID] [int] NULL
,[Name] [varchar](30) NULL
,[RecordCreated] [datetime] NULL
,[RecordUpdated] [datetime] NULL
,
) ON [PRIMARY]
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (1, N'James', CAST(N'2017-11-01T16:16:21.297' AS DateTime), CAST(N'2017-11-01T16:52:02.427' AS DateTime))
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (2, N'John', CAST(N'2017-11-01T16:41:52.347' AS DateTime), CAST(N'2017-11-01T16:41:52.347' AS DateTime))
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (3, N'Sam', CAST(N'2017-11-01T16:50:25.430' AS DateTime), CAST(N'2017-11-01T16:50:25.430' AS DateTime))
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (1, N'James', CAST(N'2017-11-01T16:16:21.297' AS DateTime), CAST(N'2017-11-01T16:52:02.427' AS DateTime))
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (2, N'John', CAST(N'2017-11-01T16:41:52.347' AS DateTime), CAST(N'2017-11-01T16:41:52.347' AS DateTime))
GO
INSERT [dbo].[Customer] ([CustomerID], [Name], [RecordCreated], [RecordUpdated]) VALUES (3, N'Sam', CAST(N'2017-11-01T16:50:25.430' AS DateTime), CAST(N'2017-11-01T16:50:25.430' AS DateTime))
GO
以下は、垂直形式で結果を返す実際のプロセスです
IF OBJECT_ID('tempdb..#tempwide') IS NOT NULL DROP TABLE #tempwide
SELECT *
INTO #tempwide -- ADD THIS TO YOUR QUERY
FROM customer a
EXEC sp_SHOWDOWN -- ADD AS THE LAST LINE
これが結果です
| CustomerID | 1 |
|---------------|---------------------|
| Name | James |
| RecordCreated | Nov 1 2017 4:16PM |
| RecordUpdated | Nov 1 2017 4:52PM |
| CustomerID | 2 |
| Name | John |
| RecordCreated | Nov 1 2017 4:41PM |
| RecordUpdated | Nov 1 2017 4:41PM |
| CustomerID | 3 |
| Name | Sam |
| RecordCreated | Nov 1 2017 4:50PM |
| RecordUpdated | Nov 1 2017 4:50PM |
| CustomerID | 1 |
| Name | James |
| RecordCreated | Nov 1 2017 4:16PM |
| RecordUpdated | Nov 1 2017 4:52PM |
| CustomerID | 2 |
| Name | John |
| RecordCreated | Nov 1 2017 4:41PM |
| RecordUpdated | Nov 1 2017 4:41PM |
| CustomerID | 3 |
| Name | Sam |
| RecordCreated | Nov 1 2017 4:50PM |
| RecordUpdated | Nov 1 2017 4:50PM |
更新(2018-02-09)
私の回答を投稿した後、 Martin Smith はFOR XML PATH
といくつかのCROSS APPLY
を使用して この問題への素晴らしく単純なアプローチ を参照するコメントを追加しました。
SQL Fiddleリンクが停止した場合に備えて、ここに彼のソリューションを含めます。
SELECT n.value('local-name(.)', 'SYSNAME') AS Col,
n.value('.', 'nvarchar(4000)')
FROM Customer c
CROSS APPLY
(SELECT c.*
FOR XML PATH('r'), TYPE) ca(x)
CROSS APPLY ca.x.nodes('/r/*') n(n)
select v
from ( values (1), (2), (4)
) val(v)
_varchar/nvarchar
_以外のフィールドを処理していても[Field] + char(13)
のシンプルさを求めている場合は、CONCAT
を使用して_CONVERT/CAST
_ボイラープレートをスキップできます(SQL v2012 +) 、投げたものをすべて処理する必要があります
https://docs.Microsoft.com/en-us/sql/t-sql/functions/concat-transact-sql
_SELECT CONCAT(1, char(13), GETDATE(), char(13), 3.0, char(13), 'A')
-------------------------------------------
1
Feb 9 2018 11:39AM
3.0
A
(1 row affected)
_
* CONCAT
は254個のパラメーターに制限されています