我有水平表(表1),我需要它将其转换为(表2)
表1:
CEO SALESMAN PRODUCT(1) PRODUCT(2) PRODUCT(3) PRODUCT(4) PRODUCT(5) ... PRODUCT(N)
------ ---------- ---------- ---------- ---------- ---------- ---------- ----------
MIKE ANDERSON 76787,00 19388,00 0,00 2723,00 217,00 6581,00
JOHN ANGELA 0,00 0,00 73088,00 0,00 0,00 0,00
JACK JEFF 24716,00 0,00 2995,00 0,00 0,00 0,00
STUART MICHAEL 0,00 23338,00 42656,00 0,00 0,00 0,00
表2:
CEO SALESMAN PRODUCTS VALUE
------- ----------- ---------- --------
MIKE ANDERSON PRODUCT(1) 76787,00
JOHN ANGELA PRODUCT(1) 0,00
JACK JEFF PRODUCT(1) 24716,00
STUART MICHAEL PRODUCT(1) 0,00
MIKE ANDERSON PRODUCT(2) 19388,00
JOHN ANGELA PRODUCT(2) 0,00
JACK JEFF PRODUCT(2) 0,00
STUART MICHAEL PRODUCT(2) 23338,00
MIKE ANDERSON PRODUCT(3) 0,00
JOHN ANGELA PRODUCT(3) 73088,00
JACK JEFF PRODUCT(3) 2995,00
STUART MICHAEL PRODUCT(3) 42656,00
MIKE ANDERSON PRODUCT(4) 2723,00
JOHN ANGELA PRODUCT(4) 0,00
JACK JEFF PRODUCT(4) 0,00
STUART MICHAEL PRODUCT(4) 0,00
MIKE ANDERSON PRODUCT(5) 217,00
JOHN ANGELA PRODUCT(5) 0,00
JACK JEFF PRODUCT(5) 0,00
STUART MICHAEL PRODUCT(5) 0,00
MIKE ANDERSON ... ...
JOHN ANGELA ... ...
JACK JEFF ... ...
STUART MICHAEL ... ...
MIKE ANDERSON PRODUCT(N) 6581,00
JOHN ANGELA PRODUCT(N) 0,00
JACK JEFF PRODUCT(N) 0,00
STUART MICHAEL PRODUCT(N) 0,00
到目前为止,我尝试将BULK INSERT Table1放入临时表中,然后处理这些数据,直到得到我想要的内容。问题是PRODUCT()列中的N是可变的,因此我无法创建具有固定列的临时表,我需要一个动态查询,以某种方式可以读取产品数量列并使用它。
BULK INSERT
BULK INSERT #temp
FROM '\\path\file.csv'
WITH
(
FIRSTROW = 1,
FIELDTERMINATOR= ';',
ROWTERMINATOR = '\n',
CODEPAGE='RAW'
);
临时表:
CREATE TABLE #temp(
col1 varchar(100) null,
col2 varchar(100) null,
col3 varchar(100) null,
col4 varchar(100) null,
col5 varchar(100) null,
...
col397 varchar(100) null,
col398 varchar(100) null,
col399 varchar(100) null,
col400 varchar(100) null
)
当我运行BULK INSERT时,我收到此错误:
Msg 4832, Level 16, State 1, Line 1
Bulk load: An unexpected end of file was encountered in the data file.
Msg 7399, Level 16, State 1, Line 1
The OLE DB provider "BULK" for linked server "(null)" reported an error. The provider did not give any information about the error.
Msg 7330, Level 16, State 2, Line 1
Cannot fetch a row from OLE DB provider "BULK" for linked server "(null)".
这是因为我创建了一个包含固定400列的临时表,并且有127个产品列。
我试图避免这样的事情:
DECLARE @NUM_ROWS INT
SET @NUM_ROWS = 123
IF @NUM_ROWS = 1
BEGIN
CREATE TABLE #temp(
col1 varchar(100) null
)
END
IF @NUM_ROWS = 2
BEGIN
CREATE TABLE #temp(
col1 varchar(100) null,
col2 varchar(100) null,
)
END
...
IF @NUM_ROWS = 400
BEGIN
CREATE TABLE #temp(
col1 varchar(100) null,
col2 varchar(100) null,
...
col4 varchar(100) null,
)
END
BULK INSERT #temp
FROM '\\path\file.csv'
WITH
(
FIRSTROW = 1,
FIELDTERMINATOR= ';',
ROWTERMINATOR = '\n',
CODEPAGE='RAW'
);
@NUM_ROWS 将是我创建临时表的列数。
有没有人知道我可以动态地将这个.csv文件导入SQL Server的方法?通过动态我的意思是创建一个临时表,其中包含我批量插入的PRODUCTS列数。或者是一种解决方法,以避免我在上面发布的错误。
答案 0 :(得分:1)
如果您将CSV打开到Excel,然后再次将其另存为CSV,则会将其格式化为具有固定数量的列。
您可以使用循环和动态SQL
创建临时表declare @sql nvarchar(max), @numcols int = 8
select @sql = ''
declare @i int = 1
select @sql = @sql + ', c' + convert(varchar(5), number) + ' varchar(10) '
from master..spt_values
where type='p' and number between 1 and @numcols
select @sql = 'create table ##temp (' + substring(@sql, 3, len(@sql)) + ')'
select @sql
exec sp_executeSQl @sql
BULK INSERT ##temp
FROM '\\path\file.csv'
WITH
(
FIRSTROW = 1,
FIELDTERMINATOR= ';',
ROWTERMINATOR = '\n',
CODEPAGE='RAW'
);
从那里开始,您只需应用Unpivot将表格从列转换为行。
答案 1 :(得分:1)
这是一种有点手动的方法:
从这里开始,它就是SQL:
Insert into Table2 Select CEO, Salesmen, 1 as ProductNum, [Product(1)] from Table1 where [Product(1)] is not null union Select CEO, Salesmen, 2 as ProductNum, [Product(2)] from Table1 where [Product(2)] is not null ... union Select CEO, Salesmen, 400 as ProductNum, [Product(400)] from Table1 where [Product(400)] is not null
当然,这400行会很难看,但你可以很容易地阅读它并计算从1到400.