SQLite3中CHECK约束内LIKE语句失效,手机号正则验证失败求助
问题分析与解决方案
核心问题原因
你的问题出在SQLite对LIKE和正则的支持逻辑上:
- SQLite的
LIKE操作符不支持正则表达式语法(如^、$、{10}这类锚点和重复次数标记),它仅识别%(任意长度字符)、_(单个字符)作为通配符,默认也不支持[0-9]这类字符集匹配。 - Python的
sqlite3模块默认未内置REGEXP函数,直接使用会报错;而SQL控制台可能已预装了相关扩展,所以能正常运行。 - 你尝试的
[0-9]重复写法无效,也是因为SQLite默认LIKE不支持字符集语法。
可行解决方案
方案1:用SQLite内置函数验证全数字(最简方案)
利用CAST()函数特性:如果字符串包含非数字字符,CAST(phone_number AS INTEGER)会返回NULL,结合已有的长度约束即可实现验证。
修改后的Customers表创建语句:
create table if not exists Customers( phone_number nvarchar(10) primary key, first_name nvarchar(15), last_name nvarchar(15), city nvarchar(20), address nvarchar(50), backup_phone nvarchar(10), password nvarchar(20), check (length(phone_number) = 10), check (phone_number != backup_phone), check (CAST(phone_number AS INTEGER) IS NOT NULL), check (length(password) >= 8 and length(password) <= 20) )
另外注意:SQLite中auto_increment必须搭配integer primary key使用,你的Products表中id_number int auto_increment写法有误,应改为id_number integer primary key autoincrement。
方案2:注册自定义REGEXP函数(最灵活方案)
在Python中通过create_function注册正则匹配函数,这样就能在CHECK约束中使用标准正则语法:
import sqlite3 import re def regexp(expr, item): reg = re.compile(expr) return reg.search(item) is not None def create_table(): customers_table = """ create table if not exists Customers( phone_number nvarchar(10) primary key, first_name nvarchar(15), last_name nvarchar(15), city nvarchar(20), address nvarchar(50), backup_phone nvarchar(10), password nvarchar(20), check (phone_number REGEXP '^[0-9]{10}$'), check (phone_number != backup_phone), check (password REGEXP '^.{8,20}$') ) """ products_table = """ create table if not exists Products( id_number integer primary key autoincrement, name nvarchar(50), img_path nvarchar(100), price nvarchar(10), description nvarchar(200), publish_year nvarchar(20), author_name nvarchar(20) ) """ with sqlite3.connect("Shopping.db") as connection: # 注册REGEXP函数 connection.create_function("REGEXP", 2, regexp) cursor = connection.cursor() try: cursor.execute(customers_table) cursor.execute(products_table) connection.commit() except Exception as e: print(e) connection.rollback()
方案3:用SQLite的GLOB操作符
GLOB支持[0-9]这类字符集匹配,语法类似简化版正则:
check (phone_number GLOB '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
或结合长度约束简化:
check (length(phone_number) = 10), check (phone_number GLOB '^[0-9]*$')
内容的提问来源于stack exchange,提问作者Mohammad Ghanayem
相关产品推荐
相关产品推荐

