如何通过 SQL Server 插入的索引有效地替换长字符串?

Posted

技术标签:

【中文标题】如何通过 SQL Server 插入的索引有效地替换长字符串?【英文标题】:How to efficiently replace long strings by their index for SQL Server inserts? 【发布时间】:2019-09-19 18:26:40 【问题描述】:

我有一个非常大的DataTable-Object,我需要通过 ODBC 从客户端将其导入 MS SQL-Server 数据库。

原始数据表有两列: * 第一列是Office Location(很长的字符串) * 第二列是booking value(整数)

现在我正在寻找将这些数据插入外部 SQL-Server 的最有效方法。我的目标是用索引自动替换每个办公室位置,而不是使用完整的字符串,因为每个位置都经常出现在初始表中。

这可以通过触发器还是通过 SQL 服务器上的视图实现?

最后我想在我的脚本中插入数据而不接触它们,因为这对于这些大量数据来说非常慢,并且让 SQL Server 完成优化。

我希望如果我插入包含 Office 位置的数据,SQL Server 会查找已导入位置的索引,然后仅使用此索引。如果该位置在索引表/视图中尚不存在,则应在此处创建一个新条目,然后使用新索引。

这里是我需要通过 ODBC 导入 SQL-Server 的数据示例:

OfficeLocation             | BookingValue
EU-Germany-Hamburg-Ostend1 | 12
EU-Germany-Hamburg-Ostend1 | 23
EU-Germany-Hamburg-Ostend1 | 34
EU-France-Paris-Eifeltower | 42
EU-France-Paris-Eifeltower | 53
EU-France-Paris-Eifeltower | 12

我在 SQL-Server 上需要的是类似于这 2 个表的结果:

OId|BookingValue      OfficeLocation             |Oid
  1|12                EU-Germany-Hamburg-Ostend1 | 1
  1|23                EU-France-Paris-Eifeltower | 2
  1|43
  2|42
  2|53
  2|12

我最初的想法是,将数据写入临时表,并使用类似智能 TRIGGER(或 VIEW?)的东西来对任何 INSERT 做出反应,以创建 2 个所需的(优化的)表。

欢迎任何提示!

【问题讨论】:

这个问题没有意义。如果数据已经在表中,为什么需要插入它?您需要在此处提供一些上下文,以便其他人知道您要做什么。 听起来您想normalize您的模型,因为您应该在专用表中定义您的办公室位置,然后使用外键通过 ID 引用它。然后您可以轻松地对其进行索引,而不必无限期地复制标签。但是,您必须编写自己的代码来维护您的办公室位置表,并且您绝对应该尽可能避免使用表触发器。也看看ADO.net framework。 样本数据和期望的结果在这里会有所帮助。这个问题目前还不清楚,无法回答。 感谢您的快速反馈。我编辑了原始问题以使其更清晰。 【参考方案1】:

是的,您可以使用INSERT 触发器创建一个视图来处理此问题。比如:

CREATE TABLE dbo.Locations (
    OId int IDENTITY(1,1) not null PRIMARY KEY,
    OfficeLocation varchar(500) not null UNIQUE
)
GO
CREATE TABLE dbo.Bookings (
    OId int not null,
    BookingValue int not null
)
GO
CREATE VIEW dbo.CombinedBookings
WITH SCHEMABINDING
AS
    SELECT
        OfficeLocation,
        BookingValue
    FROM
        dbo.Bookings b
            INNER JOIN
        dbo.Locations l
            ON
                b.OId = l.OId
GO
CREATE TRIGGER CombinedBookings_Insert
ON dbo.CombinedBookings
INSTEAD OF INSERT
AS
    INSERT INTO Locations (OfficeLocation)
    SELECT OfficeLocation
    FROM inserted where OfficeLocation not in (select OfficeLocation from Locations)

    INSERT INTO Bookings (OId,BookingValue)
    SELECT OId, BookingValue
    FROM
          inserted i
              INNER JOIN
          Locations l
              ON
                  i.OfficeLocation = l.OfficeLocation

如您所见,我们首先将所有缺失的位置添加到位置表中,然后填充预订表。

类似的触发器可以处理更新。我通常会让 Locations 表增长,而不是尝试用触发器清理它(对于不再引用的位置)。如果增长是一个问题,定期工作通常就足够了。

请注意,某些工具(例如批量插入)可能不会调用触发器,因此这些工具无法用于上述视图。

【讨论】:

以上是关于如何通过 SQL Server 插入的索引有效地替换长字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何最有效地在 SQL Server 中插入/更新几百万行?

SQL Server - 插入表太慢

SQL server 2005如何设置一个或几个字段唯一约束?

SQL Server 列存储索引更新/插入存储过程

sql server 2008r2 向带有索引的表里大批量插入数据

如何估计 SQL Server 索引大小