在我的表中,我有一个6位代码的列。
myCode CHAR(6) PRIMARY KEY CHECK ( SUBSTRING ( myCode ,1 ,1) >='0' AND
SUBSTRING ( myCode ,1 ,1) <= '9' AND ...#for all positions
还有另一种比这更快的方法吗?
答案 0 :(得分:4)
使用正则表达式:
CREATE TABLE tabq(myCode CHAR(6) PRIMARY KEY CHECK (myCode ~'^([0-9]{6})$') );
如果您只想识别不匹配此模式的记录,您可以尝试:
SELECT *
FROM tabq
WHERE myCode !~ '^\\d{6}$';
<强> Rextester Demo 强>
答案 1 :(得分:2)
简单:
mycode ~ '\d{6}'
\d
is the class shorthand for digits。
不使用其他\
转义\
,除非您使用已过时的standard_conforming_strings = off
。见:
不需要括号。
在使用^
时,您甚至不需要$
和char(6)
来锚定表达式的开始和结束(即使这不会造成伤害)。一种罕见的用例,其中数据类型并非完全无意义。参见:
较短的字符串是空白填充的,不会传递CHECK
约束
较长的字符串不会传递char(6)
类型的长度规范
(但要小心!像'1234567'::char(6)
这样的显式强制转换会默默地截断。)
CREATE TABLE tbl (mycode char(6) PRIMARY KEY CHECK (mycode ~ '\d{6}'));
我仍然建议不要使用过时的char(6)
类型。角落情况下的奇怪行为。请改用text
。然后你在regexp表达式中实际需要^
和$
:
CREATE TABLE tbl (mycode text PRIMARY KEY CHECK (mycode ~ '^\d{6}$'));
dbfiddle here
你评论过(真的是一个新问题):
那里面的数字必须与众不同?
在字符串中强制使用唯一数字并不简单。如果您安装了additional module intarray,则会有sort()
和uniq()
的优雅解决方案:
CREATE TEMP TABLE tbl3 (
mycode varchar(6) PRIMARY KEY
, CONSTRAINT chk_6_distinct_digits
CHECK (cardinality(uniq(sort(string_to_array(mycode, NULL)::int[]))) = 6)
);