This might be a stupid question. I need to have a Id field in a table. This Id is not a key (primary or whatever). The requirement says that user can input 10 digits in this field from the UI. This Id has no relation as of now with any otehr object in the system. Do you think If one can use nvarchar or bigint for this field. Does bigint would be an overhead for this purpose?
If you will ever perform any mathematical work with this column, then obviously an integral type is to be preferred. Alternatively, if this is a pure, opaque identifier, then a char or varchar column would seem to make more sense. And if leading zeros might be important, then obviously the integral types will not work, e.g. if storing a UK phone number, 01234 567890, you'd want that in a char column.
Edit and for bonus points, if it is an id that should always be ten digits:
CREATE TABLE T (
/* Other columns */
Id char(10),
constraint CK_ID_Valid CHECK (LEN(ID)=10 and not ID like '%[^0-9]%')
)
There are chances that business can ask you to start storing alphanumeric data in this key. I would suggest that you stick with nvarchar or varchar. Even if it remains numeric and not used anywhere in some kind of computation, it is perfectly valid to have it as varchar.
You may use NUMERIC(10,0) type
or if you dont any mathematical operation you can use nvarchar type.
Related
I'm learning SQL and SQLite at the moment, and from what I understand, SQLite doesn't support a datetime datatype.
However, when I run the command PRAGMA table_info(Orders); it's showing one column as being of type datetime.
I've read that In SQLite, the datatype of a value is associated with the value itself, not with its container. taken from here https://www.sqlite.org/datatype3.html
I'm trying to understand what exactly this means, which may help to explain.
Can someone help me understand what's going on here?
What you see in the column type when you execute:
PRAGMA table_info(tablename)
or:
SELECT * FROM pragma_table_info('tablename');
is the data type that was used for the definition of the column in the CREATE TABLE statement.
SQLite allows the use of anything (even nothing), as long as it is not a reserved word, as a data type.
This:
CREATE TABLE tablename (
column0 integer primary key,
column1 integer,
column2 text,
column3 real,
column4 string,
column5 something,
column6 Jack,
column7, -- no data type defined
column8 real char int -- ??,
column9 datetime
);
is a valid statement!
From all the above column definitions, SQLite will enforce type checking only for the column column0 which is defined as integer primary key.
From Datatypes In SQLite Version 3/Storage Classes and Datatypes:
Any column in an SQLite version 3 database, except an INTEGER PRIMARY
KEY column, may be used to store a value of any storage class.
When you define a column as datetime, don't expect SQLite to understand your intention and set any internal constraints so that the values you store in it will be datetime-like.
Actually, by the rules described in Determination Of Column Affinity, this column will have NUMERIC affinity.
Of course you can store datetime values in a column, as described in Date and Time Datatype, by using INTEGER, REAL or TEXT data type, depending on the form of the datetimes that you want: Unix Times, Julian day numbers or ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS") strings respectively.
In conclusion, SQLite will never complain for any value in any column defined as any data type (except for integer primary key).
It is your responsibility to make sure that you store values in the proper format that you can read/write, make calculations, compare etc.
For example, never store text datetimes in any other format than "YYYY-MM-DD HH:MM:SS.SSS" because all SQLite's datetime functions work with this format only.
To amplify #forpas's excellent answer, you can make up for SQLite's weak type-checking by using CHECK constraints in your table definitions. I frequently do that to enforce integers or string lengths, and you could use SQLite's date functions to verify that the value can be parsed as a date and lies between two values.
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 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.
In my MySQL InnoDB database, I have dirty zip code data that I want to clean up.
The clean zip code data is when I have all 5 digits for a zip code (e.g. "90210").
But for some reason, I noticed in my database that for zipcodes that start with a "0", the 0 has been dropped.
So "Holtsville, New York" with zipcode "00544" is stored in my database as "544"
and
"Dedham, MA" with zipcode "02026" is stored in my database as "2026".
What SQL can I run to front pad "0" to any zipcode that is not 5 digits in length? Meaning, if the zipcode is 3 digits in length, front pad "00". If the zipcode is 4 digits in length, front pad just "0".
UPDATE:
I just changed the zipcode to be datatype VARCHAR(5)
Store your zipcodes as CHAR(5) instead of a numeric type, or have your application pad it with zeroes when you load it from the DB. A way to do it with PHP using sprintf():
echo sprintf("%05d", 205); // prints 00205
echo sprintf("%05d", 1492); // prints 01492
Or you could have MySQL pad it for you with LPAD():
SELECT LPAD(zip, 5, '0') as zipcode FROM table;
Here's a way to update and pad all rows:
ALTER TABLE `table` CHANGE `zip` `zip` CHAR(5); #changes type
UPDATE table SET `zip`=LPAD(`zip`, 5, '0'); #pads everything
You need to decide the length of the zip code (which I believe should be 5 characters long). Then you need to tell MySQL to zero-fill the numbers.
Let's suppose your table is called mytable and the field in question is zipcode, type smallint. You need to issue the following query:
ALTER TABLE mytable CHANGE `zipcode` `zipcode`
MEDIUMINT( 5 ) UNSIGNED ZEROFILL NOT NULL;
The advantage of this method is that it leaves your data intact, there's no need to use triggers during data insertion / updates, there's no need to use functions when you SELECT the data and that you can always remove the extra zeros or increase the field length should you change your mind.
Ok, so you've switched the column from Number to VARCHAR(5). Now you need to update the zipcode field to be left-padded. The SQL to do that would be:
UPDATE MyTable
SET ZipCode = LPAD( ZipCode, 5, '0' );
This will pad all values in the ZipCode column to 5 characters, adding '0's on the left.
Of course, now that you've got all of your old data fixed, you need to make sure that your any new data is also zero-padded. There are several schools of thought on the correct way to do that:
Handle it in the application's business logic. Advantages: database-independent solution, doesn't involve learning more about the database. Disadvantages: needs to be handled everywhere that writes to the database, in all applications.
Handle it with a stored procedure. Advantages: Stored procedures enforce business rules for all clients. Disadvantages: Stored procedures are more complicated than simple INSERT/UPDATE statements, and not as portable across databases. A bare INSERT/UPDATE can still insert non-zero-padded data.
Handle it with a trigger. Advantages: Will work for Stored Procedures and bare INSERT/UPDATE statements. Disadvantages: Least portable solution. Slowest solution. Triggers can be hard to get right.
In this case, I would handle it at the application level (if at all), and not the database level. After all, not all countries use a 5-digit Zipcode (not even the US -- our zipcodes are actually Zip+4+2: nnnnn-nnnn-nn) and some allow letters as well as digits. Better NOT to try and force a data format and to accept the occasional data error, than to prevent someone from entering the correct value, even though it's format isn't quite what you expected.
I know this is well after the OP. One way you can go with that keeps the table storing the zipcode data as an unsigned INT but displayed with zeros is as follows.
select LPAD(cast(zipcode_int as char), 5, '0') as zipcode from table;
While this preserves the original data as INT and can save some space in storage you will be having the server perform the INT to CHAR conversion for you. This can be thrown into a view and the person who needs this data can be directed there vs the table itself.
It would still make sense to create your zip code field as a zerofilled unsigned integer field.
CREATE TABLE xxx (
zipcode INT(5) ZEROFILL UNSIGNED,
...
)
That way mysql takes care of the padding for you.
CHAR(5)
or
MEDIUMINT (5) UNSIGNED ZEROFILL
The first takes 5 bytes per zip code.
The second takes only 3 bytes per zip code. The ZEROFILL option is necessary for zip codes with leading zeros.
you should use UNSIGNED ZEROFILL in your table structure.
LPAD works with VARCHAR2 as it does not put spaces for left over bytes.
LPAD changes leftover/null bytes to zeros on LHS
SO datatype should be VARCHAR2