which datatype to use to store a mobile number - sql-server-2005

Which datatype shall I use to store mobile numbers of 10 digits (Ex.:9932234242). Shall I go for varchar(10) or for the big one- the "bigint".
If the number is of type- '0021-23141231' , then which datatype to use?

varchar/char long enough for all expected (eg UK numbers are 11 long)
check constraint to allow only digits (expression = NOT LIKE '%[^0-9]%')
format in the client per locale (UK = 07123 456 789 , Switzerland = 071 234 56 78)

As others have answered, use varchar for data that happens to be composed of numeric digits, but for which mathematical operations make no sense.
In addition, in your example number, did you consider what would happen if you stored 002123141231 into a bigint column? Upon retrieval, it would be 2123141231, i.e. there's no way for a numeric column to store leading 0 digits...

Use varchar with check constraint to make sure that only digits are allowed.
Something like this:
create table MyTable
(
PhoneNumber varchar(10)
constraint CK_MyTable_PhoneNumber check (PhoneNumber like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
)
if it is always the same length you might want to use char instead.

varchar(50) is good for mobile number data type . because it may sometimes contain country code for example +91 or spaces also. For comparison purpose we can remove all special characters from both side in the expresion.

Related

What is a type of my value 675763582022462206:57 in sql creating data table query?

I am creating a table with several columns in sql:
CREATE TABLE.....
and one of them is going to have values like this: 675763582022462206:57. As you see it has : in it. So what is a type of it? Is it UInt16 or String?
It must be varchar or nvarchar in this case. The database doesn't recognize ":" as a part of a number, unless you say to Windows in advanced region settings that this is your decimal point. If you can store 57 (after ":") in a different column, then you can save the number before ":" as a bigint if you wish
This value can't be stored in a numeric type due to the colon (:), so you'll have to use one of the character types - i.e., a sufficiently long char or varchar.

How to specify min and max digits for a bank account number?

Is it possible to constrain the number of digits allowed in a column of integer data type in PostgreSQL. I have the following example:
CREATE TABLE bank_accounts (
id SERIAL PRIMARY KEY
, number_account INTEGER(26) NOT NULL
);
We can enter something like:
1 -- one digit
23 -- two digits
444 -- three digits
5555 -- four digits
Etc. ... up to 26 digits.
But I want to constrain my column to store exactly 26 digits, not less and not more. How to achieve that?
A bank account number is not an integer by nature. 26 decimal digits are too much for integer or bigint anyway.
A bank account number is not a numeric value at all, really, even if we could use the type numeric for storage. It can handle 26 decimal digits easily. But it also allows fractional digits (and other decorators, like #klin commented). You can restrict to numeric(26), which is short for numeric(26,0), to remove fractional digits from storage. But that still allows fractional digits on input, which are then rounded off. And other decorators. All of these seem undesirable for a bank account number:
SELECT numeric(26) '12345678901234567890123456'
, numeric(26) '12345678901234567890123456.4' -- rounded down
, numeric(26) '12345678901234567890123456.5' -- rounded up
, numeric(26) '1e25'
, numeric(26) '1.2345e25'
, numeric(26) '+12345678901234567890123456.5'
SELECT numeric(26) '99999999999999999999999999.5' -- error after rounding up
A bank account number is more like text by nature, so data type text seems more appropriate (like #klin provided), even if that occupies a bit more space on disk (like #a_horse mentioned). 27 bytes vs. 17 bytes for numeric - or 30 vs. 20 bytes in RAM. See:
What is the overhead for varchar(n)?
However, you would not want to apply collation rules to bank account numbers. That happens with collatable types like text or varchar if your DB cluster runs with a non-C locale. Would be a void effort for only digits to begin with. But you still get slower sorting and slower indexes etc. Notably, the "abbreviated keys" feature in Postgres 9.5 or later is currently (incl. Postgres 10) disabled for non-C locales.
Putting everything together, I suggest:
CREATE TABLE bank_account (
bank_account_id serial PRIMARY KEY
-- bank_account_id integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY -- in Postgres 10+
, number_account text COLLATE "C" NOT NULL -- disable collation rules
, CONSTRAINT number_account_has_26_digits CHECK (number_account ~ '^\d{26}$')
);
Asides:
Consider an IDENTITY column instead of the serial in in Postgres 10+. Details:
https://blog.2ndquadrant.com/postgresql-10-identity-columns/
INTEGER(26) is not valid syntax in Postgres, where the integer data type has no modifiers. You can chose from int2, int4 (default integer) and int8, though - the dangling number signifying occupied bytes, not the number of digits allowed.
The maximum integer value is 2147483647, maximum bigint is 9223372036854775807. You cannot use integer types for the column.
It seems that the simplest way is to define the column as text with a check constraint:
CREATE TABLE bank_accounts (
id serial primary key,
number_account text not null check (number_account ~ '^\d{26}$')
);
The regular expression used in the check constraint means a string with exactly 26 digits.

SQL Server - Like/Pattern Matching

I'm trying to implement a check constraint on a key field. The key field is composed of a 3 character prefix, and then appended with numeric characters (which can be provided manually, but the default is to get an integer value from a sequence, which is then cast as nvarchar). The key field is defined as nvarhcar(9).
I'm doing this for multiple tables, but here is a specific example below to demonstrate:
Table name: Company
Key field: IDCompany
Key field prefix: CMP
Examples of valid keys -
CMP1
CMP01
CMP10000
CMP999999
Examples of invalid keys -
CMPdog1
steve
1CMP1
1
999999999
The check constraint I came up with was:
IDCompany LIKE 'CMP%[0-9]'
However, this is beaten by CMPdog1 etc.
What should I be using as a check constraint to enforce an unknown number of numeric characters?
I could do the following:
IDCompany LIKE 'CMP[0-9]' OR IDCompany LIKE 'CMP[0-9][0-9]' OR .... through to 6 characters
But, this seems like a clunky way of doing it, is there something smarter?
EDIT 2: This actually doesn't work, it does not exclude negative numbers:
EDIT 1:
This solution ended up working for me:
IDCompany nvarchar(9) NOT NULL CONSTRAINT DEF_Company_IDCompany DEFAULT 'CMP' + CAST((NEXT VALUE FOR dbo.sq_Company) AS nvarchar) CONSTRAINT CHK_Company_IDCompany CHECK (IDCompany LIKE 'CMP%[0-9]' AND ISNUMERIC(SUBSTRING(IDCompany,4,LEN(IDCompany)-3))=1)
EDIT 3: Solution -
As proposed in Szymon's post below.
Thanks all!
You could do something like that:
where LEFT(IDCompany, 3) = 'CMP'
and isnumeric(RIGHT(IDCompany, len(IDCompany) - 3)) = 1
and IDCompany not like '%[.,-]%'
The first part checks that it starts with CMP
The next part is to make sure that the rest is numeric but excluding negative and decimal numbers.
Well, I would reconsider the design of your table and create 3 columns:
prefix, CHAR(3), with a default as 'CMP' and a constraint to allow only 'CMP' combination
id, INTEGER
companyid, NVARCHAR(9), a computed, persisted column as sum of the first 2 columns. Most probably with an index on.
Unfortunately, SQL Server doesn't suppport regular expressions.
So there is only 2 ways to solve your problem:
Use CLR function for using regular expression. You may find more information here
Or whrite long WHERE clause like you suggested:
IDCompany LIKE 'CMP[0-9]' OR IDCompany LIKE 'CMP[0-9][0-9]' OR ....
Try this:
isnumeric(substring(IDCompany,4,len(IDCompany)))=1 and IDCompany not like '%[.,-]%'
How this works: The first three characters are fixed, so we only need to check from the 4th character onwards. So we get the required substring. Then, we use isNumeric to check if the substring is entirely numeric. Example here
EDIT: As pointed out in comments by Allan, we need an extra check to ensure that characters used in numeric strings like commas or dots are not part of the input string.

Update column in postgresql

I found out that I have a character varaying column with mistakes in a database with over 4 millon records. It contains numbers. Each number has to have 12 digits, but for some reason a lot of those numbers ended up having 10 digits.
The good news is that the only thing I have to do, is prepend '55' to each cell that only has 10 digits and starts with the number '22', leaving the ones with 12 digits untouched.
My objective is this:
UPDATE
table
SET
column = CONCAT( '55', column )
WHERE
LENGTH( column ) = 10 AND column LIKE( '22%');
I am thinking of using this:
UPDATE
telephones
SET
telephone_number = CONCAT( '55', telephone_number )
WHERE
LENGTH( telephone_number ) = 10 AND telephone_number LIKE( '22%');
Am I doing it right? If not, what would be the correct way to do it
What if instead of a string the numbers were stored as big int, same rules apply, it is still 10 digits long which means the number is lower than 3.000.000.000 and bigger than 2.000.000.000? and they all need to be the same number starting with 55
The answer is: yes, that's right. You can play around with a sample database here on SQL Fiddle. That one uses the BIGINT type. Also see this one by #gmm, which uses the VARCHAR form. Both work just like you've described them using your original syntax.

What does the specified number mean in a VARCHAR() clause?

Just to clarify, by specifying something like VARCHAR(45) means it can take up to max 45 characters? I remember I heard from someone a few years ago that the number in the parenthesis doesn't refer to the number of characters, then the person tried to explain to me something quite complicated which I don't understand and forgot already.
And what is the difference between CHAR and VARCHAR? I did search around a bit and see that CHAR gives you the max of the size of the column and it is better to use it if your data has a fixed size and use VARCHAR if your data size varies.
But if it gives you the max of the size of the column of all the data of this column, isn't it better to use it when your data size varies? Especially if you don't know how big your data size is going to be. VARCHAR needs to specify the size (CHAR don't really need right?), isn't it more troublesome?
You also have to specify the size with CHAR. With CHAR, column values are padded with spaces to fill the size you specified, whereas with VARCHAR, only the actual value you specified is stored.
For example:
CREATE TABLE test (
char_value CHAR(10),
varchar_value VARCHAR(10)
);
INSERT INTO test VALUES ('a', 'b');
SELECT * FROM test;
The above will select "a " for char_value and "b" for varchar_value
If all your values are about the same size, the CHAR is possibly a better choice because it will often require less storage space than VARCHAR. This is because VARCHAR stores both the length of the value and the value itself, whereas CHAR can just store the (fixed-size) value.
The MySQL documentation gives a good explanation of the storage requirements of the various data types.
In particular, for a string of length L, a CHAR(M) datatype will take up (M x c) bytes (where c is the number of bytes required to store a character... this depends on the character set in use).
A VARCHAR(M) will take up (L + 1) or (L + 2) depending on whether M is <=255 or >255.
So, it really depends on how long you expect your strings to be, what the variation in length will be.
NB: The documetation doesn't discuss the impact of character sets on the storage requirements of a VARCHAR type. I've tried to quote it accurately, but my guess is that you would need to multiply the string length by the character byte-width as well to get the storage requirement.
The complicated stuff you don't remember is that the 45 refer to bytes, not chars. It's not the same if you are using a multibyte character encoding. In Oracle you can specify bytes or chars explicitly.
varchar2(45 BYTE)
or
varchar2(45 CHAR)
See Difference between BYTE and CHAR in column datatypes
char and varchar actually becomes irrelevant if you have just 1 variable length field in your table, like a varchar or text. Mysql will automatically change all char to varchar.
The fixed length/size record can give you extra performance, but you can't use any variable length field types. The reason is that it will be quicker and easier for mysql to find the next record.
For example, if you do a SELECT * FROM table LIMIT 10, mysql has to scan the table file for the tenth record. This means finding the end of each record until you find the end of the 10th record. But if your table has fixed length/size records, mysql just needs to know the record size and then skip 10 x #bytes.
If you know a column will contain a small, fixed number of chars use a CHAR, otherwise use a varchar. A CHAR column is padded to the max length.
VARCHAR has a small overhead (4-8 bytes depending on RDBMS), but only uses the overhead + the actual number of chars stored.
For the values you know they are going to be constant, for example for Phone Numbers, Zip Codes etc., It is optimal to use "char" for sure.