You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用存储过程将Excel工作表数据导入SQL表的技术咨询

实现方案:用存储过程导入Excel销量数据到SQL表

嘿,我来帮你搞定这个需求——把Excel里的月度销量数据导入到带唯一约束的SQL表中,全程用存储过程实现。下面是一步步的详细方案:

1. 先创建目标SQL表

首先得搭好目标表的架子,我们需要productnamemonth作为唯一组合,直接给这俩字段加个主键约束就能保证唯一性了:

CREATE TABLE ProductMonthlySales (
    productname VARCHAR(100) NOT NULL,
    month DATE NOT NULL,
    sales INT NULL,
    CONSTRAINT PK_ProductMonthlySales PRIMARY KEY (productname, month)
);

2. 编写核心存储过程

这个存储过程要干三件事:读取Excel数据、把宽表(每个月一列)转成窄表(每行一条月度记录)、插入到目标表(还得避免重复插入)。

提前注意两点:

  • 确保SQL Server的服务账户有访问你Excel文件路径的权限(比如文件在C:\Data\Sales.xlsx,得给服务账户读权限)
  • 如果是64位SQL Server,得装64位的Microsoft Access Database Engine(ACE驱动),不然会找不到Excel驱动

存储过程代码如下:

CREATE PROCEDURE ImportProductSalesFromExcel
    @ExcelFilePath NVARCHAR(255),
    @SheetName NVARCHAR(50) = 'Sheet1' -- 默认用Sheet1,你可以按需改
AS
BEGIN
    SET NOCOUNT ON;

    -- 先建个临时表存Excel读出来的原始宽表数据
    CREATE TABLE #TempSalesData (
        Product VARCHAR(100),
        [Jul-17] INT,
        [Aug-17] INT,
        [Sep-17] INT,
        [Oct-17] INT,
        [Nov-17] INT,
        [Dec-17] INT,
        [Jan-18] INT,
        [Feb-18] INT,
        [Mar-18] INT,
        [Apr-18] INT,
        [May-18] INT,
        [Jun-18] INT
    );

    -- 用OPENROWSET读取Excel数据到临时表
    DECLARE @SQL NVARCHAR(MAX);
    SET @SQL = N'
        INSERT INTO #TempSalesData
        SELECT * FROM OPENROWSET(
            ''Microsoft.ACE.OLEDB.12.0'',
            ''Excel 12.0 Xml;HDR=YES;Database=' + @ExcelFilePath + ''',
            ''SELECT * FROM [' + @SheetName + '$]''
        );
    ';

    EXEC sp_executesql @SQL;

    -- 把宽表转成窄表,插入到目标表
    -- 用UNPIVOT来把月份列转成行记录
    INSERT INTO ProductMonthlySales (productname, month, sales)
    SELECT
        Product AS productname,
        -- 把Jul-17这种格式转成标准日期(比如2017-07-01)
        CAST('01-' + MonthCol AS DATE) AS month,
        SalesValue AS sales
    FROM #TempSalesData
    UNPIVOT (
        SalesValue FOR MonthCol IN (
            [Jul-17], [Aug-17], [Sep-17], [Oct-17], [Nov-17], [Dec-17],
            [Jan-18], [Feb-18], [Mar-18], [Apr-18], [May-18], [Jun-18]
        )
    ) AS UnpivotData
    -- 过滤掉空销量的记录(不需要的话可以删掉这个条件)
    WHERE SalesValue IS NOT NULL
    -- 跳过已经存在的product+month组合,避免主键冲突
    AND NOT EXISTS (
        SELECT 1 FROM ProductMonthlySales
        WHERE productname = UnpivotData.Product
        AND month = CAST('01-' + UnpivotData.MonthCol AS DATE)
    );

    -- 清理临时表
    DROP TABLE #TempSalesData;

    PRINT '数据导入搞定啦!';
END;

3. 调用存储过程的方式

比如你的Excel文件在C:\Sales\MonthlySalesData.xlsx,工作表名叫SalesRecords,直接这么调用就行:

EXEC ImportProductSalesFromExcel 
    @ExcelFilePath = N'C:\Sales\MonthlySalesData.xlsx',
    @SheetName = N'SalesRecords';

额外优化:支持更新已有记录

如果后续导入相同product+month组合时,你想更新销量而不是跳过,可以把上面的INSERT改成MERGE语句,替换掉原来的INSERT部分:

MERGE INTO ProductMonthlySales AS Target
USING (
    SELECT
        Product AS productname,
        CAST('01-' + MonthCol AS DATE) AS month,
        SalesValue AS sales
    FROM #TempSalesData
    UNPIVOT (
        SalesValue FOR MonthCol IN (
            [Jul-17], [Aug-17], [Sep-17], [Oct-17], [Nov-17], [Dec-17],
            [Jan-18], [Feb-18], [Mar-18], [Apr-18], [May-18], [Jun-18]
        )
    ) AS UnpivotData
    WHERE SalesValue IS NOT NULL
) AS Source
ON Target.productname = Source.productname AND Target.month = Source.month
WHEN MATCHED THEN
    UPDATE SET Target.sales = Source.sales -- 已有记录就更新销量
WHEN NOT MATCHED THEN
    INSERT (productname, month, sales)
    VALUES (Source.productname, Source.month, Source.sales); -- 没有就插入新记录

小提示

  • 如果你的Excel是旧的.xls格式,把OPENROWSET里的Excel 12.0 Xml改成Excel 8.0就行。

内容的提问来源于stack exchange,提问作者samaposha

火山引擎 最新活动