不能直接用substring(字段,1,3)提取域名,因域名长度不固定且结构复杂(含协议、端口、路径等),须结合charindex动态定位://、/、:等关键分隔符,并用case处理边界情况。

提取域名时为什么不能直接用 SUBSTRING(字段, 1, 3)?
因为域名长度不固定,SUBSTRING 的起始位置和长度必须动态计算。硬写数字会漏掉 example.com 或截断 sub.domain.co.uk。关键在于定位「协议头」和「路径分隔符」——也就是找 :// 和第一个 / 的位置。
CHARINDEX 找不到 :// 怎么办?
说明字段里可能没协议(比如存的是纯 google.com/search),或用了 https、ftp 等多种协议。稳妥做法是:先统一补前缀再处理,或用多条件判断:
- 用
CHARINDEX('://', url)找协议结束位置;若为 0,则从开头找第一个/或空格 - 若协议不存在,可假设整个字符串就是主机名,但需用
CHARINDEX('/', REPLACE(url, ' ', '/'))防止空格干扰 - 对含端口的 URL(如
http://api.example.com:8080/path),要额外处理冒号 —— 域名截止到:或/的较早者
SUBSTRING + CHARINDEX 组合的标准写法
以 SQL Server 为例,提取 https://shop.example.co.uk:443/product?id=1 中的 shop.example.co.uk:
SELECT
SUBSTRING(
url,
CHARINDEX('://', url) + 3,
CASE
WHEN CHARINDEX('/', url, CHARINDEX('://', url) + 3) > 0
THEN CHARINDEX('/', url, CHARINDEX('://', url) + 3) - (CHARINDEX('://', url) + 3)
WHEN CHARINDEX(':', url, CHARINDEX('://', url) + 3) > 0
THEN CHARINDEX(':', url, CHARINDEX('://', url) + 3) - (CHARINDEX('://', url) + 3)
ELSE LEN(url) - (CHARINDEX('://', url) + 2)
END
) AS domain
FROM urls;
注意:CHARINDEX 第三个参数是搜索起点,必须传入协议后的偏移;SUBSTRING 的长度不能为负,所以要用 CASE 拦住无路径/无端口的情况。
MySQL 或 PostgreSQL 用户别照搬,函数名和行为不同
CHARINDEX 是 SQL Server 函数,MySQL 用 LOCATE,PostgreSQL 用 POSITION,且参数顺序相反:
- SQL Server:
CHARINDEX('://', url) - MySQL:
LOCATE('://', url) - PostgreSQL:
POSITION('://' IN url) - 三者
SUBSTRING的参数顺序也不同:SQL Server 是(str, start, len),MySQL 是(str, start, len)(同),PostgreSQL 是SUBSTRING(str FROM start FOR len)
跨数据库迁移时,最易错的是 LOCATE 在 MySQL 中找不到子串返回 0,而 POSITION 在 PostgreSQL 中返回 0 表示未找到 —— 但 SUBSTRING 传入 0 作起始位会导致空结果,不是报错。










