使用记录集实现Access规范化的T-SQL替代方案咨询
把Access的Excel导入+规范化流程转成T-SQL指南
Hey there! 刚上手T-SQL就搞数据迁移+规范化,这步子迈得挺实在的,我来给你捋捋怎么把原来Access那套流程平滑搬到SQL Server里,每一步都对应上T-SQL的落地方式:
第一步:把Excel文件导入临时表
SQL Server里用OPENROWSET就能直接从Excel拉数据到临时表,前提是得先启用Ad Hoc Distributed Queries(没开的话执行一次就行)。示例代码如下:
-- 启用Ad Hoc Distributed Queries(仅需执行一次,后续可注释) sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'Ad Hoc Distributed Queries', 1; RECONFIGURE; -- 创建临时表(根据你的Excel列结构调整字段和数据类型) CREATE TABLE #Temp_Transactions ( TransactionDate DATE, CustomerName VARCHAR(100), ProductName VARCHAR(100), Amount DECIMAL(18,2) ); -- 从Excel导入数据(注意替换文件路径、Excel版本和工作表名) INSERT INTO #Temp_Transactions SELECT TransactionDate, CustomerName, ProductName, Amount FROM OPENROWSET( 'Microsoft.ACE.OLEDB.12.0', 'Excel 12.0 Xml;HDR=YES;Database=C:\YourPath\Transactions.xlsx', 'SELECT * FROM [Sheet1$]' );
小贴士:如果是64位SQL Server,得安装64位的Access Database Engine才能用
OPENROWSET读取Excel,不然会报错哦。
第二步:发现新值则更新关联表(维度表)
原来Access里判断关联表有没有新值再插入的逻辑,在SQL Server里用MERGE语句最高效——它能一次性完成「匹配则跳过,不匹配则插入」的操作。以客户维度表Dim_Customer为例:
-- 假设Dim_Customer结构:CustomerID INT IDENTITY(1,1) PRIMARY KEY, CustomerName VARCHAR(100) UNIQUE MERGE INTO Dim_Customer AS Target USING (SELECT DISTINCT CustomerName FROM #Temp_Transactions) AS Source ON Target.CustomerName = Source.CustomerName -- 匹配到就啥也不做(如果需要更新其他字段,可写WHEN MATCHED THEN UPDATE...) WHEN NOT MATCHED THEN INSERT (CustomerName) VALUES (Source.CustomerName);
同样的逻辑可以直接套用到其他关联表(比如Dim_Product),只需替换表名和匹配字段即可。
第三步:将数据迁移至主表并关联维度表主键
这一步就是把临时表的数据和维度表关联,拿到对应的主键后插入事实表。以主表Fact_Transactions为例:
-- 假设Fact_Transactions结构:TransactionID INT IDENTITY(1,1) PRIMARY KEY, TransactionDate DATE, CustomerID INT, ProductID INT, Amount DECIMAL(18,2) INSERT INTO Fact_Transactions (TransactionDate, CustomerID, ProductID, Amount) SELECT t.TransactionDate, c.CustomerID, p.ProductID, t.Amount FROM #Temp_Transactions t INNER JOIN Dim_Customer c ON t.CustomerName = c.CustomerName INNER JOIN Dim_Product p ON t.ProductName = p.ProductName;
注意:如果临时表里有维度表未覆盖的新值(理论上第二步已经处理,但怕漏网之鱼),可以用
LEFT JOIN加ISNULL兜底,或者加WHERE过滤无匹配的数据,避免插入失败。
额外实用Tips
- 临时表用完记得手动清理:
DROP TABLE #Temp_Transactions;(会话结束会自动删,但手动清理更规范) - 给维度表的名称字段加唯一约束或非聚集索引,这样
MERGE和JOIN的速度会快很多,尤其是数据量大的时候 - 如果要重复执行或处理批量数据,建议加
TRY...CATCH块捕获错误,比如:
BEGIN TRY -- 把导入、MERGE、插入逻辑放这里 END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_MESSAGE() AS ErrorMessage; -- 如需回滚事务,可加:ROLLBACK TRANSACTION; END CATCH
要是你有具体的表结构、特殊业务规则或者遇到某个步骤的报错,随时把细节抛出来,我再帮你抠细节~
内容的提问来源于stack exchange,提问作者FriedMonkey
相关产品推荐
相关产品推荐

