假设我在SQL Server中有一个存储客户电子邮件的表(几百万条记录) - 为简单起见,看起来有点如下:
CREATE TABLE [Emails]
(
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[email] [nvarchar](1000) NOT NULL
)
我的客户向我发送了每个数百万条记录的客户电子邮件列表,但所有MD5-Hash
都已加密,因此列表看起来如下:
0x3B46E0E53842A74172BA678974E93BBB
0xACAC5843E184C85AA6FF641AAB0AA644
0xD3C7BA16E02BE75142761894E8E4A125
...
我必须想出一个快速的方法来查看我的表格中存在哪些电子邮件。
基于我在网上/这里看到的一些答案,我提出了以下逻辑来做到这一点:
我创建了Emails
表的索引视图,其中MD5-Hash
列为索引:
CREATE VIEW dbo.vw_Emails
WITH SCHEMABINDING
AS
SELECT
Id
, email
, CONVERT(VARBINARY(16), HASHBYTES('MD5', LOWER(email))) AS MD5
FROM
dbo.Emails
GO
CREATE UNIQUE CLUSTERED INDEX Idx_vw_Emails ON vw_Emails (MD5)
GO
我创建了一个存储过程,它将BulkImport
给出的列表,将其转换为临时表,将其连接到我的视图并返回任何匹配的行,如下所示:
CREATE PROCEDURE Import_ReturnMatches
(
@PathToCSVFile VARCHAR(8000)
)
AS
DECLARE @fieldsep CHAR(1) = ',';
DECLARE @recordsep CHAR(1) = CHAR(10);
DECLARE @Emails TABLE
(
MD5 VARCHAR(MAX) NOT NULL
);
DECLARE @sql VARCHAR(8000) =
'CREATE TABLE #tmp
(
MD5 varchar(max) NOT NULL
);
BULK INSERT #tmp
FROM ''' + @PathToCSVFile + '''
WITH (FIRSTROW = 1, FIELDTERMINATOR = ''' + @fieldsep + ''', ROWTERMINATOR = ''' + @recordsep + ''');
SELECT *
FROM #tmp';
INSERT INTO @Emails
EXEC (@sql);
SELECT
r.*
FROM
@Emails l
JOIN vw_Email_Dim r
ON l.MD5 = r.MD5
正如您所看到的,我将导入的列类型设置为VARCHAR(MAX)
,但这只是因为没有其他功能真正起作用......这就是我被困住的地方。它似乎总是返回一个空集,即使我已将记录放在我的文件中应该匹配。
我的问题是:
答案 0 :(得分:0)
您的问题可能就是这个值:
LOWER(email)
如果您不确定使用哪种情况或编码(Windows 1252,UTF8,UTF16,UTF16LE?)从您的来源的电子邮件生成MD5哈希,那么您正在考虑需要测试所有组合匹配的哈希值。考虑我们将LOWER
更改为UPPER
的位置 - 生成完全不同的MD5哈希值:
您需要控制在源处生成MD5哈希的方式,或者向导入添加元数据(另一个字段)以描述输入的装入和编码方式。
答案 1 :(得分:0)
检查这个答案。您需要将varchar与varchar进行比较 - 我认为不是varbinary。