I am new at this so please bear with me. I have managed to take hundreds of xml documents and put them into a staging table via a single query. Looking at my data I realize that I would like it if my action-date and action-time columns were merged into a single column I will call datetime (containing datetime data type). How would I accomplish this considering that I want to do it all in one go? I am using Microsoft SQL Server 2016.
Here is my query
CREATE TABLE [dbo].[staagingTable]
(
[Counter] INT NOT NULL,
[majority] [nvarchar](max) NULL,
[congress] [int] NULL,
[session] [nvarchar](max) NULL,
[chamber] [nvarchar](max) NULL,
[rollcall-num] [int] NULL,
[legis-num] [nvarchar](max) NULL,
[vote-question] [nvarchar](max) NULL,
[vote-type] [nvarchar](max) NULL,
[vote-result] [nvarchar](max) NULL,
[action-date] [nvarchar](max) NULL,
[action-time] [nvarchar](max) NULL,
[vote-desc] [nvarchar](max) NULL,
[sourceXML] [XML] NULL
);
GO
DECLARE @Counter INT=1;
DECLARE @command VARCHAR(MAX);
WHILE @Counter<800
BEGIN
SET @command=
'
DECLARE @xmlString VARCHAR(MAX)=
(
SELECT BulkColumn
FROM OPENROWSET (BULK ''C:\Users\Owner\Documents\congress\House votes\114 congress 2015\Passage\roll' + REPLACE(STR(@Counter,3),' ','0') + '.xml'', SINGLE_BLOB) AS c
);
SET @xmlString=SUBSTRING(@xmlString,CHARINDEX(''<rollcall-vote>'',@xmlString,1),9999999);
DECLARE @xml XML=CAST(@xmlString AS XML);
INSERT INTO dbo.staagingTable(Counter, majority, congress,[session], chamber, [rollcall-num], [legis-num], [vote-question], [vote-type], [vote-result], [action-date], [action-time], [vote-desc], [sourceXML])
SELECT
' + CAST(@Counter AS VARCHAR(10)) + ',
v.value(N''majority[1]'', N''nvarchar(max)''),
v.value(N''congress[1]'', N''int''),
v.value(N''session[1]'', N''nvarchar(max)''),
v.value(N''chamber[1]'', N''nvarchar(max)''),
v.value(N''rollcall-num[1]'', N''int''),
v.value(N''legis-num[1]'', N''nvarchar(max)''),
v.value(N''vote-question[1]'', N''nvarchar(max)''),
v.value(N''vote-type[1]'', N''nvarchar(max)''),
v.value(N''vote-result[1]'', N''nvarchar(max)''),
v.value(N''action-date[1]'', N''nvarchar(max)''),
v.value(N''action-time[1]'', N''nvarchar(max)''),
v.value(N''vote-desc[1]'', N''nvarchar(max)''),
@xml
FROM
@xml.nodes(N''/rollcall-vote/vote-metadata'') AS A(v);
';
BEGIN TRY
EXEC(@command);
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH;
SET @Counter = @Counter + 1;
END
SELECT * FROM dbo.staagingTable;
GO
DROP TABLE dbo.staagingTable;
Here is a screenshot of the table my query yielded. The two columns I want to combine into one have purple symbols drawn above them.
Here is a baby version of one of my xml documents.
<rollcall-vote>
<vote-metadata>
<majority>R</majority>
<congress>114</congress>
<session>1st</session>
<chamber>U.S. House of Representatives</chamber>
<rollcall-num>6</rollcall-num>
<legis-num>H RES 5</legis-num>
<vote-question>On Agreeing to the Resolution</vote-question>
<vote-type>YEA-AND-NAY</vote-type>
<vote-result>Passed</vote-result>
<action-date>6-Jan-2015</action-date>
<action-time time-etz="17:30">5:30 PM</action-time>
<vote-desc>Adopting rules for the One Hundred Fourteenth Congress</vote-desc>
</vote-metadata>
</rollcall-vote>
UPDATE
As per Cam Bruce's suggestion I made the changes seen in the screenshot below, which also contains the accompanying error.
ATTEMPT #2
ATTEMPT #3
ATTEMPT #4
ATTEMPT
This attempt is using Shnugo's suggestion. The two columns were merged but they seem to be the columns from the dummy values and not my table.
ATTEMPT 2
attempt 3
假设日期和时间字符串的格式与屏幕快照中的格式相同,则可以使用xquery concat()
函数将它们连接起来:
v.value(N''concat(action-date[1], concat('''' '''', action-time[1]))'', N''nvarchar(max)''),
If I understand you correctly, all the reading process from XML into your staging table is successfully done. Now you want to combine these two columns to a typed DATETIME
(good idea!)
btw: For your next question: Try to avoid posting irrelevant code...
Unfortunately the used format is really bad (culture and language dependant!) and is not matching one of the pre-defined ones
Try it like this:
SET LANGUAGE ENGLISH;
--Some dummy values for testing
DECLARE @Dummy TABLE([action-date] NVARCHAR(MAX),[action-time] NVARCHAR(MAX));
INSERT INTO @Dummy VALUES
('6-Jan-2015','5:30 PM')
,('8-Jan-2015','2:10 PM')
,('22-Jan-2015','11:04 AM')
,('10-Mar-2015','00:00 AM');
--The existing [action-date] can be converted with code "106". In order to allow
--the usage of your time format I first combine them on string level and then
--re-convert them to `DATETIME` using format "100"
SELECT CONVERT(DATETIME,CONVERT(VARCHAR(12),CONVERT(DATETIME,d.[action-date],106),100)+ ' ' + d.[action-time],100)
FROM @Dummy AS d
The result
2015-01-06 17:30:00.000
2015-01-08 14:10:00.000
2015-01-22 11:04:00.000
2015-03-10 00:00:00.000
When your reading is done, complete and ready all your former XML data is now within your table dbo.staagingTable
.
Try this to first add a new column and then use my code to set its value
There's a final SELECT
to check the result. Very simple...
ALTER TABLE [dbo].[staagingTable] ADD CombinedDate DATETIME NULL;
GO
SET LANGUAGE ENGLISH;
UPDATE [dbo].[staagingTable]
SET CombinedDate=CONVERT(DATETIME,CONVERT(VARCHAR(12),CONVERT(DATETIME,[action-date],106),100)+ ' ' + [action-time],100);
SELECT [action-date],[action-time],CombinedDate
FROM [dbo].[staagingTable];
GO
DROP TABLE dbo.staagingTable
Create a datetime field in the [dbo].[staagingTable]
and modify the insert query for that new field and populate it with CONVERT(datetime,'action-date[1]'+' '+action-time[1] , 100)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.