I am having a problem with a check constraint in Oracle SQL Developer with Oracle 11g Express Edition.
I want to check if my postal code which is stored as CHAR just contains numbers and no other signs.
Tried various possibilities but nothing worked...
PLZ VARCHAR(5) NOT NULL
ADD CONSTRAINT TC_PLZ CHECK (PLZ LIKE '[0-9][0-9][0-9][0-9][0-9]')
Thanks and best regards,
Michael
Use regexp_like():
ADD CONSTRAINT TC_PLZ CHECK ( regexp_like(PLZ, '^[0-9]{5}$') )
Oracle -- like most databases -- only supports the ANSI standard wildcards in LIKE. These are % for zero or more characters and _ for exactly one character.
Regular expressions are much more powerful (although generally slower).
This might be a bit more efficient:
ADD CONSTRAINT TC_PLZ CHECK (translate(PLZ, '0123456789', '000000000') = '00000')
although I would go with the regular expression for clarity.
If you want to use regular expression patterns you need to use a regex function in the CHECK constraint. This will work:
create table t23 (
PLZ VARCHAR(5) NOT NULL
, CONSTRAINT TC_PLZ CHECK (regexp_LIKE(plz, '^[0-9]{5}$'))
);
Although there's no need for regex; here's an alternative implementation:
create table t42 (
PLZ NUMBER(5,0) NOT NULL
, CONSTRAINT T42_PLZ CHECK (length(plz)=5)
);
It's good practice to store numeric values using the correct datatype.
Check out this LiveSQL demo.
As #MT0 points out, the numeric implementation is not correct if a valid value can start with a leading zero. My purist data modeller persona states that values which must be a fixed number of digits should start at 10000 (for five digit values). However, I must admit I know of one system that did permit leading zeroes in a "numeric" field; they compounded this by allowing variable level values, which meant code 0300 identified something different from 00300. What larks!
Related
How to change column type from varchar2(10) to char(10) without losing existing data using oracle developer?
ALTER TABLE TBL_NAME
MODIFY (CRTE CHAR(10));
Will it impact existing data?
It should not impact existing data.
See this SQL Fiddle.
I would reconsider changing varchar2 for char. Char will take up more space on HDD as char will always take N bytes. And if your strings are not execatly 10 characters, all of them char will be pain for searches.
There is really no reason to do this. As this "Ask Tom" answer, explains, the two are stored equivalently.
If you want to ensure that the value has exactly 10 characters, then use a check constraint:
ALTER TABLE TBL_NAME ADD CONSTRAINT CHECK (LEN(CRTE) = 10);
The difference is padding the string in result sets, and that is often better handled on an ad-hoc basis. Trailing spaces can be quite tricky to deal with.
If you really want to change the column type, you can use:
alter table t modify ( x char(10) );
This should be safe with existing data, because you are not reducing the length of the column.
I have to make oracle constraints that checks if username is minimum 3 and maximum 10 lowercase letters.
I have used
constraint usernameSMALLCASE check (
REGEXP_Like(username,'^[a-z]{10}$') or
REGEXP_Like(username,'^[a-z]{9}$') or
REGEXP_Like(username,'^[a-z]{8}$') or
REGEXP_Like(username,'^[a-z]{7}$') or
REGEXP_Like(username,'^[a-z]{6}$') or
REGEXP_Like(username,'^[a-z]{5}$') or
REGEXP_Like(username,'^[a-z]{4}$') or
REGEXP_Like(username,'^[a-z]{3}$')
)
However, it is not working.
Somehow, putting $ is causing problem. But I have to put $ to make sure end of the end of line char is also small case.
Your code should work if your column is declared correctly. But you can drastically simplify it:
constraint usernameSMALLCASE check ( REGEXP_Like(username, '^[a-z]{3,10}$') )
Obviously there are other methods besides regular expressions for handling this. However, you have started down the regular expression route and it is simple enough using one.
If you insist on a fixed length column, you can express this as:
constraint usernameSMALLCASE check ( REGEXP_Like(username, '^[a-z]{3,10} *$') )
Create constraint for
username = lower(username) and length(username) > 3
The max length you can enforce by data type
username VARCHAR2(10 CHAR) NOT NULL
Note, regular expression ^[a-z]{3,10}$ is not fully reliable, see Character Class '[: :]' in Regular Expressions
A non-working example is this one:
ALTER SESSION SET NLS_SORT = XSPANISH;
BEGIN
IF REGEXP_LIKE('ch', '^[a-d]$') THEN
DBMS_OUTPUT.PUT_LINE('TRUE');
ELSE
DBMS_OUTPUT.PUT_LINE('FALSE');
END _IF;
END;
Returns TRUE (despite h is not between a-d) because ch in traditional Spanish is considered as one sorting character.
I think a 100% reliable constraint would be like this:
REGEXP_LIKE(TRANSLATE(username, 'abcdefghijklmnopqrstuvwxyz', '**************************'), '^\*{3,10}$')
AND username NOT LIKE '%*%'
I am currently creating a database project wherein it only accepts a valid phone number that starts with "09" then the rest are any numbers, although it should be limited to only 11 numbers including 09. With my code below, it accepnt only 11 numbers but even when I tried numbers 63256115426 like that it can still be accepted.
([ContactNo]>=(0) AND [ContactNo]<=(9999999999.))
The first issue you've out there is that you're using the wrong datatype for phone numbers, thus you need to use a proper on which is in your case CHAR(11)/VARCHAR(11).
Then you need to create the constraint as the following:
CREATE TABLE MyTable (
ContactNo varchar(255)
CONSTRAINT CK_ContactNo2
CHECK (ContactNo LIKE '09[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
);
INSERT INTO MyTable(ContactNo) VALUES ('11111') -- Fail
INSERT INTO MyTable(ContactNo) VALUES ('09123456789')-- Succeed
and don't forgot to drop the previous one that if you're no re-creating your table.
You need to have your phone contact in a CHAR(11) and not in any numeric datatype, because the first 0 will be mathematically removed.
As I see, your constraint matche a numerical datatype and not a char string.
With the proper datatype, the constraints give by Sandra Guilep Zouaoui Zandeh is the right one.
You must take a numerical datatype for any columsn only if you need to compute the data. As far as I remenber I have never seen any calculus over phone numbers...
When creating a table in SQL SERVER, I want to restrict that the length of an INTEGER column can only be equal 10.
eg: the PhoneNumber is an INTEGER, and it must be a 10 digit number.
How can I do this when I creating a table?
If you want to limit the range of an integer column you can use a check constraint:
create table some_table
(
phone_number integer not null check (phone_number between 0 and 9999999999)
);
But as R.T. and huMpty duMpty have pointed out: a phone number is usually better stored in a varchar column.
If I understand correctly, you want to make sure the entries are exactly 10 digits in length.
If you insist on an Integer Data Type, I would recommend Bigint because of the range limitation of Int(-2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647))
CREATE TABLE dbo.Table_Name(
Phone_Number BIGINT CONSTRAINT TenDigits CHECK (Phone_Number BETWEEN 1000000000 and 9999999999)
);
Another option would be to have a Varchar Field of length 10, then you should check only numbers are being entered and the length is not less than 10.
I would recommend you to use varchar as phone number(only for phone numbers as some phone numbers may contain hyphen,phus sign) and restrict the length to 10 ie, varchar(10).
As correctly pointed by a_horse_with_no_name in comments you can put constraint on the numbers to be of specified range like this:
check (phone_number between 0 and 9999999999)
Also on a side note:-
You will receive a error message like this if you use numbers outside the range of int -2147483648 through 2147483647
Arithmetic overflow error converting expression to data type int.
So you will not be able to use all the int of length 10 in your case.
As per me Phone number should not be stored in integer as we are not going to do any numeric operation on it like adding dividing .we are going to treat it as string for e.g. finding all number with ISD say '91' or STD '022' etc secondly if you switch to make it integer you have to handle overflow
I don't think there is a way to limit if you use number fields like int, bigint, smallint, and tinyint
Make a varchar(10) field and validate before insert
Still you need to use int field to store the phone number, you will need to restrict before in your application
Make column varchar and create a check that it strictly should have 10 characters
create table some_table
(
phone_number varchar(10) check (len(phone_number)=10)
);
First consider internal and external format:
Yes, a telephone number can be stored as an integer. You would have to assure however that all numbers are stored in the same format, e.g. as the international number without the plus sign. 4940123456 would then be a German number for instance, as 49 is the German country code. To analize the number later, however, would be difficult; country codes can be 1 to 4 digits, followed by a presumably unknown number of area code digits. But just to know a number and not to know its structure may be sufficient for your purposes. With check constraints you could assure that the number is positive and not longer than, well, how long is the longest number allowed? Be aware: Everytime you show the number, you may have to format the output (in the example given: add a leading plus sign to the number).
The other way would be to store phone numbers as strings. That would make it possible to store numbers such as '+49-40-123456'. Then the internal format is the same as the external. Advantage: You wouldn't have to think of formatting the output everytime you show the number. But you could even change the format on output if you wanted (remove dashes or replace the plus sign with the actual county dial code or remove country and area code for local calls, etc.) You would have to decide whether to enforce a certain format or not. If not, then numbers could look very different '123456', '004940123456', '040/123456', ... To enforce a certain format, you would write a function (because of the complexity of such a format) and use that in a check constraint. Or write an insert trigger (this should be a BEFORE INSERT trigger, because you want to change a value; as T-SQL doesn't provide this, you would use an INSTEAD OF INSERT trigger instead) to have the field formatted as you desire.
My recommendation is:
CREATE TABLE trial_table (phone_number VARCHAR(13));
The column can be used for international numbers too.
I have a column, say PROD_NUM that contains a 'number' that is left padded with zeros. For example 001004569. They are all nine characters long.
I do not use a numeric type because the normal operation on numbers do not make sense on these "numbers" (For example PROD_NUM * 2 does not make any sense.) And since they are all the same length, the column is defined as a CHAR(9)
CREATE TABLE PRODUCT (
PROD_NUM CHAR(9) NOT NULL
-- ETC.
)
I would like to constrain PROD_NUM so it can only contain nine digits. No spaces, no other characters besides '0' through '9'
REGEXP_LIKE(PROD_NUM, '^[[:digit:]]{9}$')
You already received some nice answers on how to continue on your current path. Please allow me to suggest a different path: use a number(9,0) datatype instead.
Reasons:
You don't need an additional check constraint to confirm it contains a real number.
You are not fooling the optimizer. For example, how many prod_num's are "BETWEEN '000000009' and '000000010'"? Lots of character strings fit in there. Whereas "prod_num between 9 and 10" obviously selects only two numbers. Cardinalities will be better, leading to better execution plans.
You are not fooling future colleagues who have to maintain your code. Naming it "prod_num" will have them automatically assume it contains a number.
Your application can use lpad(to_char(prod_num),9,'0'), preferably exposed in a view.
Regards,
Rob.
(update by MH) The comment thread has a discussion which nicely illustrates the various things to consider about this approach. If this topic is interesting you should read them.
Works in all versions:
TRANSLATE(PROD_NUM,'123456789','000000000') = '000000000'
I think Codebender's regexp will work fine but I suspect it is a bit slow.
You can do (untested)
replace(translate(prod_num,'0123456789','NNNNNNNNNN'),'N',null) is null
Cast it to integer, cast it back to varchar, and check that it equals the original string?
In MSSQL, I might use something like this as the constraint test:
PROD_NUM NOT LIKE '%[^0-9]%'
I'm not an Oracle person, but I don't think they support bracketed character lists.
in MS SQL server I use this command:
alter table add constraint [cc_mytable_myfield] check (cast(myfield as bigint) > 0)
Not sure about performance but if you know the range, the following will work.
Uses a CHECK constraint at the time of creating the DDL.
alter table test add jz2 varchar2(4)
check ( jz2 between 1 and 2000000 );
as will
alter table test add jz2 varchar2(4)
check ( jz2 in (1,2,3) );
this will also work
alter table test add jz2 varchar2(4)
check ( jz2 > 0 );