简体   繁体   中英

Combining date and time into datetime for a large number of xml files in a staging table at one go for Microsoft SQL Server

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

尝试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

t

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

UPDATE How to use this with your project

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM