MySQL create table by SQL file made strange table structure - mysql

I played with MySQL DB 5.6 as some kind of praxis. As tool for creating table I used Navicat and made table with this
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for promet
-- ----------------------------
DROP TABLE IF EXISTS `traffic`;
CREATE TABLE `traffic` (
`p_id` bigint(20) NOT NULL AUTO_INCREMENT,
`p_cbr` bigint(20) DEFAULT NULL,
`p_invnum` bigint(20) DEFAULT NULL,
`p_issued` date DEFAULT NULL,
`p_returned` date DEFAULT NULL,
`p_deadtime` smallint(4) DEFAULT NULL COMMENT 'end date',
PRIMARY KEY (`p_id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4;
but when I uploaded it on hosting place by phpmyadmin I got table where each column (field) got small key on the right end? I expected that only p_id is indexed field (on the right side is grey key) but all fields also have yellow key! Under Action column for all fields is visible:
Change | Drop | Key pic |Primary| U Unique| More
Beside this, Navicat presented empty date type fields with Null contents, here, on hosting place, it's filled with 0000-00-00 and I'm not sure how to set up SQL in order to check that some particular isn't filled up, e.g. I used ISNULL on my local machine, like:
select * FROM traffic where p_invnum='$par1' AND ISNULL(p_returned)
Did I make some error or it's phpmyadmin feature? Thank you.

In phpmyadmin I changed theme to another, called "original", environment is now more classic, simple but structure options of mentioned table now looks different, just as I expected. Why, I don't know.
Moreover, empty date type fields, filled up with 0000-00-00 instead Null (as default values), doesn't force me to correct queries, probably MySQL accept 0000-00-00 as Null itself.

Related

mysql get table structure with column collation

I need to get table full structure as one string.
I use SHOW CREATE TABLE my_table but lack column collation information
CREATE TABLE `my_table` (
`col_1` int(11) NOT NULL AUTO_INCREMENT,
`col_2` varchar(255) NOT NULL,
PRIMARY KEY (`col_1`),
KEY `col_2` (`col_2`)
) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4
Espected:
Instead col_2 varchar(255) NOT NULL,
I want col_2 varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
One strange thing:
I don't understand why certains tables show also the column colation with SHOW CREATE TABLE but others no. However if I look the structure table in phpmyadmin all tables show column collation (when the column is varchar or text type)
One last note:
If I use SHOW FULL COLUMNS ... all columns have also their collation info (even if are showing or not in SHOW CREATE TABLE)
So if I have not other option I try to recreate the creation table string manually from SHOW FULL COLUMNS result. But i think that this is a hard and risky work ...
All that I need to use in a personal tool to compare when have structure change (between two servers)

MYSQL copy fields from one table's structure and add them to another tables

I've added some additional fields for my table in db. Now I need to have this additional fields in other few tables. So the question is - can I somehow copy those fields from source table and add them to another tables? Both mysql console and phpmyadmin variants woulbe be nice. Thanks!
A phpmyadmin variant would be to export the table's structure only (Export->Custom->Choose "Structure"). After that, you will get something like this in the exported SQL file:
CREATE TABLE `table` (
`id` int(10) NOT NULL,
`name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
At that point, you can go ahead and remove the last line of the query and the parenthesis after the CREATE TABLE. Then, go ahead and substitute the [other_table] name and change the query to match the following:
ALTER TABLE `[other_table]`
ADD `id` int(10) NOT NULL,
ADD `name` varchar(50) DEFAULT NULL;
Notice how all I did was change CREATE to ALTER and add ADD before each field.
NOTE: This is not very useful on such a trivial example, but when dealing with large amounts of columns, it could prove somewhat useful.

MYSQL allowing me to insert nulls in PK and FK

I have been testing a database i am doing right now and i am noticing that it is letting me insert null values into fields that are part of a primary key, despite stating in the script that the value of the field should be NOT NULL. I am using MAC's MySQL Workbench, and I have been googling around and can't figure out why this is happening. (Maybe I am too brain-fried right now... I am even starting to doubt myself)
Part of the script of the database creation (these are the tables I have tested..):
DROP DATABASE IF EXISTS solytierra ;
CREATE DATABASE IF NOT EXISTS solytierra DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE solytierra ;
DROP TABLE IF EXISTS solytierra.Cliente ;
CREATE TABLE IF NOT EXISTS solytierra.Cliente (
CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(100) NULL,
EmailGeneral VARCHAR(45) NULL,
Web VARCHAR(45) NULL,
Notas VARCHAR(150) NULL,
insertado Timestamp,
CONSTRAINT pk_Cliente PRIMARY KEY (CIF)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS solytierra.PersonaContacto ;
CREATE TABLE IF NOT EXISTS solytierra.PersonaContacto (
Cliente_CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(50) NOT NULL,
Apellidos VARCHAR(100) NOT NULL,
Notas VARCHAR(150) NULL,
CONSTRAINT pk_PersonaContacto PRIMARY KEY (Cliente_CIF , Nombre , Apellidos),
CONSTRAINT fk_PersonaContacto_Cliente FOREIGN KEY (Cliente_CIF)
REFERENCES solytierra.Cliente (CIF)
ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB;
...
It will let me create Clients without CIF, "PersonaContacto" without Cliente_CIF or without "Nombre"....
I have also tested other databases that i already had that used to work and it is happening the same in an all them.
Got it!!
I don't know what sql mode i was running on by default, but with this:
SET sql_mode = TRADITIONAL;
It is now running perfectly! I didn't know that there were different sql modes! Thanks a lot to everyone for your time and efforts! It really helped me to see that the problem was in my workbench, not the code and look for the answer accordingly! I hope this thread will be useful for future beginners like me!
If the value being stored in the column CIF is actually a NULL, then the expression LENGTH(CIF) should also return NULL. (If it's a zero length string, then LENGTH(CIF) will return 0.
To verify:
SELECT c.CIF, LENGTH(c.CIF) FROM solytierra.Cliente c ;
SELECT c.CIF FROM solytierra.Cliente c WHERE c.CIF IS NULL;
If you are running an INSERT statement, I can't explain the behavior you are observing, either MySQL allowing a NULL value to be stored or MySQL providing an implicit default value.)
If it's a zero length string being stored, that's the behavior we would expect if the columns were not explicitly declared to be NOT NULL but were later declared to part of the primary key. It's also the behavior we'd expect if the column were defined NOT NULL DEFAULT ''.
When the NOT NULL is omitted from the column declaration and the column is later declared to be part of the PRIMARY KEY, MySQL will use an an implicit default value based on the datatype of the column (zero length string for VARCHAR, zero for an integer, etc.)
But I'm not able to reproduce the problem you report, with the table definitions you've posted.
I recommend you check the table definition by getting the output from:
SHOW CREATE TABLE solytierra.Cliente;

String comparison not working in databases, files... could the character set be an issue?

I recently encountered a strange problem with strings:
I had 2 tables:
| AgentCodes | CREATE TABLE `AgentCodes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`AgentName` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `AgentName` (`AgentName`),
) ENGINE=ndbcluster AUTO_INCREMENT=319 DEFAULT CHARSET=latin1 |
and
| AgentNumbers | CREATE TABLE `AgentNumbers` (
`AgentName` varchar(32) NOT NULL,
`TelephoneNumber` varchar(64) NOT NULL,
PRIMARY KEY (`id`),
KEY `AgentName` (`AgentName`),
KEY `TelephoneNumber` (`TelephoneNumber`),
) ENGINE=ndbcluster AUTO_INCREMENT=62 DEFAULT CHARSET=latin1 |
LIKE didn't work on AgentCodes.AgentName table, I guessed it was because AgentName had unicode charset, so I changed charset on that field to Latin1.
Now the problem is AgentNumbers table is used as realtime table for AsteriskPBX queue
Basically, I get the name of the Agent and put caller in that queue.
For example I get the name JohnDoe, the conf file looks like this:
[JohnDoe]
musicclass = temp
timeout = 35
member => SIP/...
And I get an error saying no such queue. I knew what the problem was so I copied the name from the database to that conf file and it worked.
My question is what could cause that problem, to see 2 strings one in file and other in database, copy/paste them in a third file (where they still look identical) and they are not recognized as being the same?
I guess it has something to do with Encoding/Charset, but I would like to hear why :)
Don't forget MySQL LIKE does character wise comparison, not string comparisons. So things like trailing spaces matter. And we don't have the actual SQL, for example is it a literal or variable you are comparing to.
Also, why have AgentName in 2 different tables? This doesn't look normalised, and of course you are finding out now why normalisation matters.

Inserting a value into one table based on insert from another table

I have this table for users that stores their usernames and other data, thats done like this (stripped down):
CREATE TABLE `prod_users` (
`p_user_id` INT(11) NOT NULL AUTO_INCREMENT,
`p_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`p_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`p_user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
Each time a user signs up, he'll provide a company name as well.
There's another table called prod_profiles, which stores profile details like phone nos. fax nos. etc.
CREATE TABLE `prod_profiles` (
`pf_gen_id` INT(11) NOT NULL AUTO_INCREMENT,
`pf_user_id` INT(11) NOT NULL DEFAULT '0',
`pf_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`pf_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`pf_gen_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
When a new user signs up and his details are added to prod_users, is it possible to automatically add his new user_id, user_name and comp_name details to prod_profile using MySql itself? Since each user will have a new p_user_id and we wont know it, it'll be difficult using php. Can this be achieved inside MySql itself without any problems?
It isn't difficult using PHP, since you have the LAST_INSERT_ID() available for use, be it via mysql_insert_id() or mysqli::$insert_id, PDO::lastInsertId() or whatever your API provides. As long as you call the two INSERT statements in immediate succession on the same script (it is connection dependent), MySQL will supply the correct p_user_id.
However, you can use an AFTER INSERT trigger to force MySQL to create the new row automatically:
CREATE TRIGGER build_profile AFTER INSERT ON prod_users
FOR EACH ROW
BEGIN
INSERT INTO prod_profiles
(pf_user_id, pf_user_name, pf_comp_name)
VALUES (NEW.p_user_id, NEW.p_user_name, NEW.p_comp_name)
END
Review the MySQL CREATE TRIGGER syntax reference for full details and options.
You can use the next mysql function: LAST_INSERT_ID(); which returns the last auto increased id.
Therefore , add a user and then add a prod_profile , while pf_user_id value will be the returned value of last_insert_id().
INSERT INTO `prod_users`(`p_user_name`,`p_comp_name`) VALUES('Dan' , 'Stackover')
INSERT INTO `prod_profiles`(`pf_user_id`,`pf_user_name`,`pf_comp_name`) VALUES(LAST_INSERT_ID(),'Dan','Stackover')
Please notice: I have to say , that storing the username and company_name twice for the same user in two different tables is a reall waste...
Consider re-thinking about your DB structre and logic.