Sometimes you have to store a string of numbers in a CHAR column. Probably because the string of digits represents an account number or something similar and storing as an INTEGER or BIGINT doesn't really make sense. The account number could have leading zeros that would be lost if stored as an integer. Parts of the account number could store special information, like positions 2,3 and 4 identify what department an account belongs to and it might be useful to be able to select digit_string[2,4]. There are plenty of reasons to store numerical data in a string.
What is the best way to ensure that all of the characters in the string are actually numbers?
This is what I do, is there a better way to do it?
alter table my_table add constraint check (replace(rtrim(digit_string), " ", "x")::bigint >= 0) constraint my_table_ck1; insert into my_table (digit_string) values ("123456"); 1 row(s) inserted. insert into my_table (digit_string) values ("abc123"); 1213: A character to numeric conversion process failed insert into my_table (digit_string) values (" 123456"); 1213: A character to numeric conversion process failed update my_table set digit_string = "xyzpdq" where digit_string = "123456"; 1213: A character to numeric conversion process failed
The constraint will try to cast the digit string to a BIGINT, if this works then all of the characters in the string are numbers. If it doesn't work we get an SQL error and the bad data never makes it into our database.
The replace(rtrim()) stuff attempts to capture leading white space in the digit string that would not cause the cast to a BIGINT to fail.
There are plenty of other ways to accomplish the same thing, but I like this way.
You could rely on the application to check the digit string before it inserts/updates the database, but I'm pretty sure this isn't the best way.
You could write a stored procedure that is run by insert/update triggers, but I don't think that is more efficient than the check constraint/cast to BIGINT method. This would have the benefit of being able to raise a user defined SQL error instead of the odd -1213 error, though.