我在sql server表中有一个列,其中服务器名称是数据。我需要将服务器名称拆分为两列。主机名转到一列,实例名转到另一列。任何帮助将不胜感激。
想为此目的使用ssis。
示例: -
Input Expected Output
column1 Column2 Column3
ServerName Hostname InstanceName
wsql1005x\Express wsql1005x Express
答案 0 :(得分:1)
您可以使用两种途径。您可以使用脚本组件或使用派生列任务及其中的表达式。该解决方案使用该方法。
你可以在一个派生的列转换中完成所有这些逻辑但我不希望维护噩梦对我最坏的敌人。相反,自由使用派生列,这样你就有机会调试它。
此解决方案不处理拆分可能为空的列。由于源数据不允许,我不想进一步使解决方案复杂化。这种方法 处理默认的,未命名的实例。
您已选择将服务器名称和实例存储在nvarchar(max)字段中。除非你有理由需要4000多个字符,否则你不仅浪费空间并弄乱优化器,你还会让SSIS感到痛苦。
SSIS通过对内存中的数据进行操作来获取其功能。它根据给定列的最大大小分配内存。除大对象类型LOB外,它们由数据类型DT_TEXT,DT_NTEXT,DT_IMAGE标识。那些引擎无法为内存分配足够的内存,因此将内存中的指针传送到磁盘上代表此数据的文件。磁盘速度很慢所以如果你想要获得良好的性能,你现在就知道为什么你没有得到它。
然后,诀窍是将您的数据从LOB类型中取出并合理化。计算机名称的最大长度是多少?好吧,完全限定的域名限制为255个字节,而实例名称限制为16.不需要去maths.stackexchange.com看你的最大长度超过10倍。
我一直都喜欢让我的源系统完成工作,所以在我原来的提取查询中
SELECT 'wsql1005x\Express' AS ServerName
UNION ALL
SELECT 'localhost'
UNION ALL
SELECT @@ServerName;
我会用一个显式的强制转换来写它到我的最大可能长度
SELECT
(D.ServerName AS nvarchar(542)) AS ServerName
FROM
(
SELECT 'wsql1005x\Express' AS ServerName
UNION ALL
SELECT 'localhost'
UNION ALL
SELECT @@ServerName
) D(ServerName);
关于主题的一些有用的SO问题
开启节目
此组件的目的是查找令牌的位置。由于\
字符也是转义符,我们必须使用双反斜杠,我们实际上只是一个。
在英语中,此表达式查看ServerName列中是否存在反斜杠。如果是,则我们将位置存储在名为TokenLocation
的新列中。如果它不存在,那么我们将指示令牌是字符串的最终位置。如果没有附加实例,这将允许我们切断服务器名称。
TokenLocation
FINDSTRING(ServerName,"\\",1) > 0 ? FINDSTRING(ServerName,"\\",1) : LEN(ServerName)
这里我们将确定第一个单词的结束边界和第二个单词的起始边界。如果令牌位置的值与字符串的总长度匹配,那么我们知道字符串中没有反斜杠令牌。然后,我们在令牌的左侧和右侧看一个字符位置,以识别我们的停止和开始边界。对于没有令牌的单词,我们会将这两个位置都设置到单词的末尾。
EndOfFirstWord
(TokenLocation != LEN(ServerName)) ? TokenLocation - 1 : LEN(ServerName)
BeginOfSecondWord
(TokenLocation != LEN(ServerName)) ? TokenLocation + 1 : LEN(ServerName)
此时,我们知道
TokenLocation
1
)EndOfFirstWord
)BeginOfSecondWord
)LEN(TokenLocation)
)所以它只是变成了我们的专栏。
主机名
SUBSTRING(ServerName,1,EndOfFirstWord)
实例名
SUBSTRING(ServerName,BeginOfSecondWord,LEN(ServerName) - TokenLocation)