【问题标题】:Constraint for phone number in SQL ServerSQL Server 中电话号码的约束
【发布时间】:2016-07-02 22:26:10
【问题描述】:

电话号码限制为 7 位数字。如何在 SQL Server 中检查它是否为 7 位数字?

CREATE TABLE Customer
(
    C_ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
    C_Name VARCHAR(255) NOT NULL,
    Phone INT 
);

【问题讨论】:

  • 您不需要将电话号码存储为整数。你永远不会在电话号码上做数学。将它们存储为 varchar。您可以轻松添加一个约束来检查 LEN = 7 和值不像 '^[0-9][0-9][0-9][0-9][0-9][0-9][0- 9]'
  • 尝试使用十进制(7,0) 会导致错误以存储更多长度
  • 它与 Phone VARCHAR CHECK(DATALENGTH(Phone)=7) 一起使用
  • 您可以将其设为 CHAR(7),但我认为您想要的约束首先是个坏主意。例如,在美国,电话号码实际上是 10 位数字,前三位是可选的。与外国打交道时,您可能希望存储国家代码以及数字的多少位。
  • 当一个澳大利亚人想要存储他们的电话号码时会发生什么?在该国家/地区,电话号码最多可包含 8 个字符。

标签: sql-server check-constraints


【解决方案1】:

死灵术。
如果你真的只是想要一个强制执行 7 位数字的约束,那么你可以这样做:

DECLARE @phone TABLE 
(
     phone_id int NOT NULL PRIMARY KEY 
    ,phone_name nvarchar(255) NOT NULL 
    ,phone_number int NULL CHECK 
    (
        phone_number >= 1000000 -- or > 999999
        AND 
        phone_number <= 9999999 -- or < 10000000    
    ) 
);



INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 1 AS phone_id, N'Person 1' AS pn, '1000000' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 2 AS phone_id, N'Person 2' AS pn, '9999999' AS phone_number; 


INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 3 AS phone_id, N'Person 3' AS pn, '+1000000' AS phone_number; 

现在,如果您需要前面的零,您可以这样做:

SELECT RIGHT(('0000000') + CAST(phone_number as varchar(32)), 7) AS number FROM @phone 

但是,如果您只是从 google 搜索到这里寻找一般电话号码的约束条件...

那么,我一直在思考电话号码的正确限制是什么。

查看questions 723587,我能够确定电话号码的最大长度为31位。

鉴于我们需要发送 SMS,这意味着它必须是一个有效号码才能发送,我认为防止人们在现场乱扔垃圾的最佳“约束”是将其声明为十进制(31, 0)。您还可以在其中放置一个检查约束以确保电话号码的最小长度(最小号码)。另外,您需要检查该数字是否不小于零。

如果你绝对想用 varchar 来做,那么看看 Gordon Linoff 的帖子,我确定它需要在数字的开头允许一个 + 号,所以最终字段类型是 varchar(32)。

如果您不需要 +,则将字段设为 varchar 是多余的。

您可以对 varchar 施加的一个约束是

DECLARE @phone TABLE 
(
     phone_id int NOT NULL PRIMARY KEY 
    ,phone_name nvarchar(255) NOT NULL
    -- ,phone_number varchar(31) NULL CHECK (phone_number NOT LIKE '%[^0-9]%') -- result of check may not be false
    -- ,phone_number varchar(31) NULL CHECK (phone_number NOT LIKE '%[^0-9+]%') -- result of check may not be false
    ,phone_number varchar(32) NULL CHECK 
    (
        (
            phone_number NOT LIKE '%[^0-9]%'
            OR 
            (
                SUBSTRING(phone_number, 1, 1) = '+' 
                AND 
                SUBSTRING(phone_number, 2, 35) NOT LIKE '%[^0-9]%'
            )
        )
        AND phone_number <> '' 
    ) 

    --CONSTRAINT chk_phone CHECK (phone_number NOT LIKE '%[^0-9]%') -- check that no number is not a digit 
);

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 1 AS phone_id, N'Person 1' AS pn, '123' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 2 AS phone_id, N'Person 2' AS pn, '+123' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 3 AS phone_id, N'Person 3' AS pn, '++123' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 4 AS phone_id, N'Person 3' AS pn, '' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 5 AS phone_id, N'Person 3' AS pn, NULL AS phone_number; 

请注意,这允许 NULL 值。
要禁止它们,请将字段类型从 NULL 更改为 NOT NULL

另外,请注意,您应该始终区分数据和实际显示值。

因此,我认为存储电话号码的最佳方式是:

DECLARE @phone TABLE 
(
     phone_id int NOT NULL PRIMARY KEY 
    ,phone_name nvarchar(255) NOT NULL 
    ,phone_number decimal(31,0) NULL CHECK 
    (
        -- phone_number > 0 AND 
        phone_number > 99
    ) 
);



INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 1 AS phone_id, N'Person 1' AS pn, '112' AS phone_number; 

INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 2 AS phone_id, N'Person 2' AS pn, '+12126879970' AS phone_number; 

-- INSERT INTO @phone ( phone_id, phone_name, phone_number )
-- SELECT 3 AS phone_id, N'Person 3' AS pn, '-12126879970' AS phone_number; 

-- INSERT INTO @phone ( phone_id, phone_name, phone_number )
-- SELECT 4 AS phone_id, N'Person 4' AS pn, '++12126879970' AS phone_number; 

-- INSERT INTO @phone ( phone_id, phone_name, phone_number )
-- SELECT 5 AS phone_id, N'Person 5' AS pn, '+' AS phone_number; 

-- INSERT INTO @phone ( phone_id, phone_name, phone_number )
-- SELECT 6 AS phone_id, N'Person 6' AS pn, '0' AS phone_number; 

-- INSERT INTO @phone ( phone_id, phone_name, phone_number )
-- SELECT 7 AS phone_id, N'Person 7' AS pn, '+0' AS phone_number; 


INSERT INTO @phone ( phone_id, phone_name, phone_number )
SELECT 8 AS phone_id, N'Person 8' AS pn, '100.1' AS phone_number; 


SELECT * FROM @phone 

请注意,由于+SOMETHING 是一个有效数字,您还可以在其中添加一个+。
像 0.0 这样的值会被截断为 0。
一个警告:这允许像 '100.1' 等值。

如果您有一个使用空格和/或破折号的格式化电话号码作为输入,只需执行REPLACE(REPLACE('YOUR_PHONE_NUMBER', ' ', ''), '-', ''),该约束将有助于防止替换未捕获的任何不需要的格式字符进入数据库(比如大括号)。

【讨论】:

    【解决方案2】:

    假设您有一个学生表。为了检查接触长度,以下代码起作用:

    ALTER TABLE Student ADD CONSTRAINT SD_CHK check(contact like '[0-9]*10');
    

    希望对你有帮助

    【讨论】:

      【解决方案3】:

      根据NANP,美国的七位电话号码是NXX-XXXX,其中N是2-9,X是0-9。此外,第二个和第三个数字不能都是 1。假设您只想存储真实的 NANP 电话号码,您可以使用以下约束:

      ALTER TABLE Customer
      ADD CONSTRAINT CHK_Phone_valid
      CHECK (Phone >= 2000000 AND Phone <= 9999999 and Phone / 10000 % 100 <> 11)
      

      如果您想添加区号,则需要使用 bigint 和不同/额外的约束。此外,任何类型的内部电话号码、分机、区号、国际电话号码等都会有不同的要求。

      作为经常在数据库中处理大量(仅 NANP)电话号码的人,我确实发现将它们保持为数字格式是理想的,因为它更快、更小,并且具有防止各种默认情况下的格式问题。尽管对于大多数用户来说,这可能都没有实际意义。

      【讨论】:

        【解决方案4】:

        您最好将电话号码存储为 varchar2char 类型。在Oracle中,您可以通过正则表达式检查电话号码的验证:

        CREATE TABLE Customer
        (
            C_ID INT NOT NULL PRIMARY KEY,
            C_Name VARCHAR(255) NOT NULL,
            Phone char(10),
            CONSTRAINT valid_phone_number 
            CHECK (REGEXP_LIKE(p_number, '^0\d{9}|\d{10}$'))
        );
        

        '^0\d{9}|\d{10}$' 表示电话号码必须以数字 0 开头,然后是 9 或 10 位数字(即 01646947314(11 位)或 0123456789(10 位)有效,123456789 或 0123456 无效)。您可以通过删除“|”将此代码修改为 7 位数字在正则表达式中并更改为 d{7}。 希望这可以帮助您(或其他遇到类似问题的人)!

        【讨论】:

          【解决方案5】:

          不要将电话号码存储为整数。例如,一些有效数字可能以 0 开头——如果不是今天,也许是将来。要进行验证检查,您可以使用like

          CREATE TABLE Customer (
              C_ID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
              C_Name VARCHAR(255) NOT NULL,
              Phone CHAR(7), -- you might not want to have such a precise length
              CONSTRAINT chk_phone CHECK (phone not like '%[^0-9]%') -- check that no number is not a digit 
          );
          

          或者,你可以写:

          CONSTRAINT chk_phone CHECK (phone like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9]') -- check that no number is not a digit 
          

          【讨论】:

            【解决方案6】:

            它适用于 Phone VARCHAR CHECK(DATALENGTH(Phone)=7)

            【讨论】:

              猜你喜欢
              • 2020-11-28
              • 1970-01-01
              • 2022-06-16
              • 1970-01-01
              • 1970-01-01
              • 2015-08-07
              • 2019-01-01
              • 2011-04-19
              • 1970-01-01
              相关资源
              最近更新 更多