MySQL auto increment plus alphanumerics in one column - mysql

I am new to MySQL coming from Oracle. I have a requirement to create a table with the primary key in one column but with the following format.
X-A letter stating the country of origin e.g. S for Spain, Z for Zimbabwe e.tc (we have five countries of origins only)
YYYYMMDD - Date in that format,
9999 - 4 digit office code.
9999999 - 7 right padded sequence number from a sequence in Oracle (auto increment in MySQL)
This gives me a primary key like Z2010013150110000001 as the primary key.
My question is how do I generate the part of 9999999 in MySQL. In Oracle it would have been
select 'Z'||to_char(sysdate, 'YYYYMMDD')|| 5011||cust_id.nextval from dual;

auto_increment can't be just part of a field, so a single column might be a wash. So how about:
CREATE TABLE xxxxx (
id int unsigned not null auto_increment,
rest_of_that_key char(xx) not null,
// other goodies
PRIMARY KEY (id)
);
Then you can SELECT CONCAT(rest_of_that_key, LPAD(id, 7, '0')) AS full_key FROM xxxxx.
Or even better, so you can use those office codes and dates to filter data with:
CREATE TABLE xxxxx (
id int unsigned not null auto_increment,
country_code char(1) not null,
sysdate date not null,
office_code smallint unsigned not null,
// other goodies
PRIMARY KEY (id),
KEY country_code (country_code)
// etc, index the useful stuff
);
Then you can use SELECT CONCAT(country_code, DATE_FORMAT(sysdate, '%Y%m%d'), office_code, LPAD(id, 7, '0')) AS full_key FROM xxxxx and even throw in a WHERE office_code = 1256 AND sysdate >= '2010-01-01' without having to somehow parse that huge string.
If you really need that huge string as a single-field primary key, you'll have manually increment things yourself. I still wouldn't recommend doing it though, MySQL really likes its PKs to be numeric.

Related

how to avoid blank space while using char field in sql

I have two tables one is a customer table and the second is sales table.
I need to create a query to display customer name, customer_id and number of Gadgets bought (write two queries using different syntaxes of JOIN). Example : “John Barry - 111 bought 5 gadgets”.
CUSTOMERS_JS
create table CUSTOMERS_JS (
CUSTID smallint not null,
CUSTNAME char(50) not null,
primary key(CUSTID)
);
STORE_SALES_JS
create table STORE_SALES_JS (
SALEID smallint not null,
SALETS datetime not null,
GADGETID smallint not null,
EMPID smallint not null,
CUSTID smallint not null,
primary key(SALEID),
foreign key(GADGETID) references ELEC_items_JS(GADGETID),
foreign key(EMPID) references Store_EMPS_JS(EMPID),
foreign key(CUSTID) references CUSTOMERS_JS(CUSTID)
);
I did this query
select concat(CUSTNAME,' - ',STORE_SALES_JS.CUSTID,' bought ',count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID
but there is too much space between the name and the '-'. I tried to change the name field to varchar and it worked as it supposed to work but I need it to work with char(50) as well.
Thanks to scaisEdge help I managed to fix this issue while using rtrim function
select concat(rtrim(CUSTNAME),' - ',STORE_SALES_JS.CUSTID,' bought ',count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID
if you must use char and not varchar but need a trimmed result in your select you could trim ( or rtrim or ltrim) your custname for remove the spaces
select concat(rtrim(CUSTNAME),' - '
,STORE_SALES_JS.CUSTID,' bought '
,count(STORE_SALES_JS.GADGETID),' gadgets') as result
from CUSTOMERS_JS,STORE_SALES_JS
where STORE_SALES_JS.CUSTID = CUSTOMERS_JS.CUSTID
group by STORE_SALES_JS.CUSTID,CUSTNAME
order by STORE_SALES_JS.CUSTID

Database table design task

There is a factory with 15 production lines. Each production line, every day gets its own table and needs to fill in efficiency measurements every hour. Table consists of columns (time periods) and categories with sub categories which makes it around 80 rows. Here is an example:
Could you give me any suggestions with database design ?
Requirements:
Server needs to get all table data for specific day fast.
Server needs to retrieve a specific cell (by line number, date, time period and subcategory) fast.
create table metric
( -- a thing to track
metricNum int auto_increment primary key, -- 1,2,3 etc
metricName varchar(200) -- ie: "Splat & spild", etc
);
create table efficiency
( -- all data for all lines for all time
id int auto_increment primary key,
lineNum int not null,
theDate day not null,
metricNum int not null,
theHour int not null,
theCount int not null
-- add indexes of use
-- add foreign key (FK) constraint(s), such as to metric
);
That's it. Two tables. Not each line with a new table each day.

MySQL is not failing when deliberately inserting `NULL` in Primary Key AUTO_INCREMENT column

I have created a table empInfo as follow
CREATE TABLE empInfo (
empid INT(11) PRIMARY KEY AUTO_INCREMENT ,
firstname VARCHAR(255) DEFAULT NULL,
lastname VARCHAR(255) DEFAULT NULL
)
Then I run below Insert statements :-
INSERT INTO empInfo VALUES(NULL , 'SHREE','PATIL');
INSERT INTO empInfo(firstname,lastname) VALUES( 'VIKAS','PATIL');
INSERT INTO empInfo VALUES(NULL , 'SHREEKANT','JOHN');
I thought first or Third SQL will fail as empid is PRIMARY KEY and We are trying to insert NULL for empid .
But MYSQL proved me wrong and all 3 queries ran successfully .
I wanted to know Why it is not failing when trying to insert NULL in empid column ?
Final Data available in table is as below
empid firstname lastname
1 SHREE PATIL
2 VIKAS PATIL
3 SHREEKANT JOHN
I can figure out that it has something releted to AUTO_INCREMENT But I am not able to figure out reason for it . Any pointers on this .
This behaviour is by design, viz inserting 0, NULL, or DEFAULT into an AUTO_INCREMENT column will all trigger the AUTO_INCREMENT behaviour.
INSERT INTO empInfo VALUES(DEFAULT, 'SHREEKANT','JOHN');
INSERT INTO empInfo VALUES(NULL, 'SHREEKANT','JOHN');
INSERT INTO empInfo VALUES(0, 'SHREEKANT','JOHN');
and is commonplace practice
Note however that this wasn't however always the case in versions prior to 4.1.6
Edit
Does that mean AUTO_INCREMENT is taking precedance over PRIMARY KEY?
Yes, since the primary key is dependent on the AUTO_INCREMENT delivering a new sequence prior to constraint checking and record insertion, the AUTO_INCREMENT process (including the above re-purposing of NULL / 0 / DEFAULT) would need to be resolved prior to checking PRIMARY KEY constraint in any case.
If you remove the AUTO_INCREMENT and define the emp_id PK as INT(11) NULL (which is nonsensical, but MySql will create the column this way), as soon as you insert a NULL into the PK you will get the familiar
Error Code: 1048. Column 'emp_id' cannot be null
So it is clear that the AUTO_INCREMENT resolution precedes the primary key constraint checks.
It is exactly because of the auto increment. As you can see, no empid values are null in the db. That is the purpose of auto increment. Usually you would just not include that column in the insert, which is same as assigning null
As per the documentation page:
No value was specified for the AUTO_INCREMENT column, so MySQL assigned sequence numbers automatically. You can also explicitly assign 0 to the column to generate sequence numbers. If the column is declared NOT NULL, it is also possible to assign NULL to the column to generate sequence numbers.
So, because you have an auto increment null-allowed field, it ignores the fact that you're trying to place a NULL in there, and instead gives you a sequenced number.
You could just leave it as is since, even without the not null constraint, you can't get a NULL in there, because it will auto-magically convert that to a sequenced number.
Or you can change the column to be empid INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL if you wish, but I still think the insert will allow you to specify NULLs, converting them into sequenced numbers in spite of what the documentation states (tested on sqlfiddle in MySQL 5.6.6 m9 and 5.5.32).
In both cases, you can still force the column to a specific (non-zero) number, constraints permitting of course.
CREATE TABLE empInfo (
empid INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
firstname VARCHAR(255) DEFAULT NULL,
lastname VARCHAR(255) DEFAULT NULL
)
Not sure but i think it will work :)

Column name or number of supplied values does not match table definition.

I'm writing a program in visual to use a database to make a PC builder type program. When I try to insert data into the PROCESSORS table, I get the following error:
ERROR:
Column name or number of supplied values does not match table definition.
Since my other inserts work fine, I don't know what's wrong with this one.
DROP TABLE PROCESSORS
DROP TABLE MOTHERBOARDS
DROP TABLE SOCKET_TYPE
DROP TABLE STORE;
CREATE TABLE PROCESSORS (
PRODCUT_ID VARCHAR(20) PRIMARY KEY,
BRAND VARCHAR(6) NOT NULL,
CORES INTEGER NOT NULL,
SPEED DECIMAL NOT NULL,
INTEGRATED_GPU VARCHAR(40) NOT NULL);
CREATE TABLE STORE(
STORE_ID VARCHAR(20) PRIMARY KEY,
PRODUCT_ID VARCHAR(20) NOT NULL,
PRODUCT_NAME VARCHAR(50) NOT NULL,
STORE VARCHAR(30) NOT NULL,
PRICE INTEGER NOT NULL);
/*Newegg Product I7-4470*/
INSERT INTO PROCESSORS VALUES('BX80646I74770','Intel',4,3.4,'None');
INSERT INTO STORE VALUES('N82E16819116900','BX80646I74770','Intel Core I7-4470 Haswell','Newegg',309.99);
Looks like you're entering a decimal in to an integer in the STORE Price column :)
Edit: Just noticed the DECIMAL type of the column is missing the impelementation syntax, e.g. DECIMAL(2,2). As it stands, according to here the default when not provided is DECIMAL(10, 0) which is a 10 digit integer basically. Provide precise parameters to the DECIMAL data type to allow the correct numbers with decimal places to be added, this will fix the INSERT problem.

SQL Server 2008 - Create a table

My table is:
CREATE TABLE Employee
(
EID INT PRIMARY KEY NOT NULL,
Efname VARCHAR(60) NOT NULL,
Elname VARCHAR(60) NOT NULL,
Efathername VARCHAR(60) NOT NULL,
Ephone VARCHAR(25) NOT NULL,
Eaddress VARCHAR(1000),
Erecruitment_date DATE NOT NULL,
Epension VARCHAR(25),
Ecomment VARCHAR(5000) DEFAULT'',
CONSTRAINT CXX_Epension CHECK(Epension NOT LIKE'%[^0-9]%'),
CONSTRAINT CXX_Ephone CHECK(Ephone NOT LIKE'%[^0-9]%'),
CONSTRAINT CXX_Efname CHECK(Efname NOT LIKE'%[^ a-zA-zا-ی]%'),
CONSTRAINT CXX_Elname CHECK(Elname NOT LIKE'%[^ a-zA-zا-ی]%'),
CONSTRAINT CXx_Efathername CHECK(Efathername NOT LIKE'%[^ a-zA-zا-ی]%'),
)
I want EID to be 10 characters long, and the first 6 characters are year and month of Erecruitment_date (example: 2001 02). The next 4 should be the first four characters of Ephone (example: 0098)
If I understand correctly, your requirement is this:
First 6 digits of EID should be the year and month parts of Erecruitment_date e.g. '200501' for date '20050101'.
Next 4 digits of EID should be the first 4 digits of Ephone e.g. '1234' for phone number '12345678'
The constraint can then be written as:
CONSTRAINT CXX_Test CHECK
(substring(cast(eid as varchar),1,4)=cast(year(erecruitment_date) as varchar)
AND substring(cast(eid as varchar),5,2) = right('00' + cast(month(erecruitment_date) as varchar),2)
AND substring(cast(eid as varchar),7,4) = substring(ephone,1,4)
)
Note that you are storing EID as an int, so you need to ensure that the value coming in from your application is a 10-digit number to begin with. Otherwise, 1, 01, 001 and 000001 are all the same as far as int is concerned.
Use substring() to select the particular year,date and phone number.
Use concat() to concatenate them and assign to EID.
Reference :
SUBSTRING
CONCAT
But logically, this may not always produce a unique ID. Consider, x and y got recruited on the same day and same year. And say their phone numbers has the same first four digits. They will have same EID.