Reputation: 13896
I want to limit my varchar columns to have only ascii characters within a specified range, say 0-9 or A-F (for hex characters) What would my constraint look like?
Upvotes: 0
Views: 3726
Reputation: 2638
Etny showed an elegant trick using a double negative ! Otherwise to validate hex numbers, I'd have to do something like (Mac LIKE '[a-f0-9][a-f0-9][a-f0-9]'..12 times)
since I'm validating a MAC address and annoyingly, you cant specify repetition like \d{12}
in regex. Plus I needed it to have a fixed size, so here is my adaptation:
CREATE TABLE #HexTest
(
Mac varchar(12)
CONSTRAINT CK_Mac_12Hex_Only --names make error msgs useful!
CHECK (Mac NOT LIKE '%[^a-f0-9]%' AND LEN(Mac) = 12)
)
INSERT INTO #HexTest values('5ca1ab1eD00d') -- good
INSERT INTO #HexTest values('DeadDa7aba5e') -- good
INSERT INTO #HexTest values('Dad`sDebac1e') -- bad chars
INSERT INTO #HexTest values('Ca5cadab1e') -- too short
INSERT INTO #HexTest values('Deba7ab1eDeal') -- too long, fails for size
DROP TABLE #HexTest
I was trying to do something like this:
CHECK (len(CONVERT(binary(6), Mac, 2)) = 6)
(which works in Oracle with hextoraw
), but it throws an error for invalid values here. So it didn't work. I wish there was a function that tries to parse and just returns null when there is an error. Maybe something like Parse vs. TryParse or maybe if IsNumeric
worked for Hex...
Upvotes: 0
Reputation:
Here's something that should work:
CREATE TABLE #TMP
(
TEST nvarchar(20) CHECK ( TEST NOT LIKE '%[^A-F0-9]%' )
)
INSERT INTO #TMP values('A1') -- WORKS
INSERT INTO #TMP values('G1') -- FAILS
Upvotes: 2
Reputation: 35141
You're storing a number. Your column type should therefore be a number, an int.
On display, convert that number to a hexadecimal representation, either in the frontend, or with a User Defined Function on the server.
Upvotes: 1
Reputation: 6636
You can easily apply a regex expression to a check constraint to do this.
CREATE TABLE [Account]
(
[AccountNumber] nvarchar(20) CHECK (dbo.RegexMatch(
[AccountNumber], '^[A-Z]{3,5}\d{5}-\d{3}$' ) = 1),
[PhoneNumber] nchar(13) CHECK (dbo.RegexMatch(
[PhoneNumber], '^\(\d{3}\)\d{3}-\d{4}$' ) = 1),
[ZipCode] nvarchar(10) CHECK (dbo.RegexMatch(
[ZipCode], '^\d{5}(\-\d{4})?$' ) = 1)
)
Upvotes: 2