2016-08-10 5 views
0

у меня есть CSV файл, как показано нижединамического создания таблицы на основе первенствовать столбцов

accont| prod|Item |Tag |LDESC|may13|jun13|jul13|jun16 
a |b |c | d | s | 20 | 20.3|30.2 |34 
x |y |z | c | s | 21 | 23.3|30.4 |35 

Каждый месяц мы получаем файл, как это, но не имеют ни малейшего представления, как, сколько месяцев будет присутствовать в том, что файл.

Здесь необходимо, чтобы каждый месяц мне приходилось загружать данные в базу данных и динамически переносить столбец месяца в строку.

Любая помощь будет очень признательна.

+0

Вы проверили мой ответ? Было ли это полезно? – gofr1

ответ

0

Вот одно решение (объяснение в комментариях к коду):

USE tempdb 
--here we declare variables 
DECLARE @string nvarchar(max), --this will store csv data as a single string 
     @xml xml,    --here is a variable that will hold @string converted in xml 
     @table_create nvarchar(max), --holds xsxript to drop and create temporary table 
     @columns nvarchar(max), --will hold the columns like [may13],[jun13],[jul13],[jun16] 
     @sql nvarchar(max)  --here will be generated query with unpivot 

--Load csv into a variable 
SELECT @string = BulkColumn 
FROM OPENROWSET(BULK N'D:\test.csv', SINGLE_CLOB) AS Document 

--convert it to xml (we need only first row to get column headers 
SELECT @xml =CAST('<row>'+'<col>'+REPLACE(SUBSTRING(@string,1,CHARINDEX(CHAR(10),@string)),'|','</col><col>')+'</col>'+'</row>' as xml) 

--generate a table creating script 
SELECT @table_create = N' 
    USE tempdb; 
    IF (OBJECT_ID(N''##tempCSVload''))IS NOT NULL DROP TABLE ##tempCSVload; 
    CREATE TABLE ##tempCSVload ('+STUFF(@table_create,LEN(@table_create),1,')') +';' 

EXEC sp_executesql @table_create 

--Now we shall BULK INSERT into temp table 
BULK INSERT ##tempCSVload 
FROM N'D:\test.csv' 
WITH 
(
    FIRSTROW = 2, 
    FIELDTERMINATOR = '|', --CSV field delimiter 
    ROWTERMINATOR = '\n', --Use to shift the control to next row 
    TABLOCK 
) 

--The number and names of monthYY columns are unknown so we take them from sys.columns table 
SELECT @columns = ISNULL(@columns,'') + ','+QUOTENAME(name) 
FROM sys.columns 
WHERE [OBJECT_ID] = OBJECT_ID(N'##tempCSVload') 
AND column_id > 5 --First 5 are skipped as there are not part of pivoting 

--Generate the UNPIVOT script 
SELECT @sql = N' 
SELECT * 
FROM ##tempCSVload 
UNPIVOT (
    [Values] FOR [Dates] IN ('+STUFF(@columns,1,1,'')+') 
) as unpvt' 

--And EXECUTE 
EXEC sp_executesql @sql 

Выход:

accont prod Item Tag  LDESC Values Dates 
a  b  c  d  s  20  may13 
a  b  c  d  s  20.3 jun13 
a  b  c  d  s  30.2 jul13 
a  b  c  d  s  34  jun16 
x  y  z  c  s  21  may13 
x  y  z  c  s  23.3 jun13 
x  y  z  c  s  30.4 jul13 
x  y  z  c  s  35  jun16 

Вы можете добавить INSERT INTO YourTable к SELECT @sql = N' как:

SELECT @sql = N' 
INSERT INTO YourTable 
SELECT * 
FROM ##tempCSVload 
UNPIVOT (
    [Values] FOR [Dates] IN ('+STUFF(@columns,1,1,'')+') 
) as unpvt' 

Для вставки данные прямо в таблице с фиксированными столбцами и типами данных. Обратите внимание, что [Values] хранится как nvarchar(max) и ночь имеют пространства, так что лучше использовать CAST([Values] as float) как:

SELECT @sql = N' 
SELECT accont, 
     prod, 
     Item, 
     Tag, 
     LDESC, 
     CAST([Values] as float) as [Values], 
     [Dates] 
FROM ##tempCSVload 
UNPIVOT (
    [Values] FOR [Dates] IN ('+STUFF(@columns,1,1,'')+') 
) as unpvt' 
+0

Спасибо за ваш ответ ... Я пробовал вышеуказанный запрос, im получая ошибку «у вас нет разрешения на массовую загрузку», есть ли другая возможность, например, ssis или какой-либо другой метод. – sqlbeginner

+0

Если имена столбцов определены - SSIS - лучший способ, но в вашем случае есть динамические. Чтобы получить разрешение на массовую загрузку, вам необходимо предоставить роль bulkadmin для вашего входа. – gofr1

Смежные вопросы