sql
sql, postgres database/postgresql, mysql, etc
- 1 SQL
- 2 PostgreSQL
- 2.1 management (copied from /log/log_05/node77.html 2007-05-11)
- 2.2 substitute the old table with a new table, but the same name(2006-08-28)
- 2.3 2007-03-20 pattern matching via regular expression:
- 2.4 2007-05-11 create user in version 8.2
- 2.5 2007-05-11 migrate graphdb
- 2.6 2008-11-06 add a forein key column to a table
- 2.7 2009-9-16 change postgresql character encoding
- 3 MySQL
- 3.1 2009-10-25 database encoding (character set)
- 3.2 2007-04-26 set the pager for the mysql client, '-p' is to let the server ask for password.
- 3.3 2007-04-26 starting commands in mysql client
- 3.4 2009-9-20 stock (149SNP) database
- 3.5 2007-06-11 user/privilege management
- 3.6 2007-06-11 enable network access
- 3.7 2005-12-10 copy table to file
- 3.8 2007-06-11 load data into table from a file (copy in postgresql)
- 3.9 2007-09-27 regular expression search
- 3.10 2007-10-10 no 'full join' for mysql
- 3.11 2007-10-10 varchar syntax
- 3.12 2008-01-09 transaction
- 3.13 2008-01-09 table
- 3.14 2008-01-28 TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
- 3.15 2008-02-03 standard mysql readme table with automatic updates on user and date
- 3.16 2008-01-28 replicate mysql (master-slave)
- 3.17 2008-02-18 foreign key
- 3.18 2008-04-09 rename database
- 3.19 2008-08-08 poking database status
- 3.20 2008-08-11 reserved keyword
- 3.21 2008-08-14 mysql SSL connection
- 3.22 2009-5-19 Procedure
1 SQL
1.1 2007-10-22 subquery, embedded select, select from another select results
according to http://dev.mysql.com/doc/refman/5.1/en/subqueries.html:
select * from calls where ecotypeid= (select distinct ecotypeid from calls where duplicate=4);
1.2 2008-04-11 multi-table update syntax in MySQL and PostgreSQL
The task is to update the same column in a new table according to an old table. Where to put the old table/alias is different in MySQL and PostgreSQL.
In MySQL, put all tables together:
update tmp1 t1, tmp2 t2 set t1.id=t2.id where t1.name=t2.name;
In PostgreSQL, put old table in a from clause:
update tmp2 t2 set id=t1.id from tmp1 t1 where t1.name=t2.name;
1.2.1 2009-9-2 update table to values from a select query (mysql)
basically treat the select query as a new table:
update phenotype_method, (select method_id, stddev(value) as std, min(value) as minv from phenotype_avg group by method_id) as newt set phenotype_method.min_value=newt.minv, phenotype_method.stddev=newt.std where phenotype_method.id=newt.method_id;
1.3 delete syntax
1.3.1 2008-07-21 multi-table delete syntax in MySQL and PostgreSQL
MySQL claims, http://dev.mysql.com/doc/refman/5.0/en/delete.html, to be able to deal with table alias. But it's not true or i didn't try hard enough. It only supports this:
delete from table1 using table1 inner join table2 where table2.id=table1.table2_id and table2.method_id!=5;
Postgresql supports table alias.
1.4 2008-07-22 outer join between the same table
Two aliases of the same table, alias 1 has a narrowing condition, alias 2 has one too.
MySQL needs an extra where clause to repeat the alias 1 narrowing condition. further adding or just repeating alias 2's in where clause doesn't work (MySQL sucks)
select c1.gene_id, c1.list_type_id, c1.original_name, c2.gene_id as gene_id2, c2.list_type_id from candidate_gene_list c1 left outer join candidate_gene_list c2 on c1.gene_id=c2.gene_id and c1.list_type_id=1 and c2.list_type_id=2 where c1.list_type_id=1 order by gene_id2;
postgresql doesn't:
select c1.gene_id, c1.list_type_id, c1.original_name, c2.gene_id as gene_id2, c2.list_type_id from candidate_gene_list c1 left outer join candidate_gene_list c2 on c1.gene_id=c2.gene_id and c1.list_type_id=1 and c2.list_type_id=2 order by gene_id2;
1.5 2008-10-08 store binary data in database
Two ways of doing it. First is to use the binary data type of database. Second is to encode the binary data, store it as text in database, decode it upon checking out.
1.5.1 2008-10-08 binary data type in database
It depends on the database and the connecting library.
postgresql is able to do so under psycopg2. Check this example (although it doesn't show whether checking database binary out restores the file):
#!/usr/bin/env python
import psycopg2
import sys conn = psycopg2.connect("dbname='myforum' user='johndoe' host='localhost'")
curs = conn.cursor()
f = open(sys.argv[1], 'rb')
binary = f.read()
curs.execute("UPDATE usertable SET avatar_image = %s WHERE username = %s", (psycopg2.Binary(binary), sys.argv[2]))
conn.commit()
2008-10-08 mysql fails in the Sqlalchemy/Elixir library. I used Elixir's Binary data type (there're others to try). able to put in but fail to restore it upon writing it out in wb mode. Maybe it is just some sort of writing file trick.
2008-11-06 Sqlalchemy/Exlixir's Binary type can handle smoothly both for mysql and postgresql. The failure happened before is the truncation due to the default size of binary (blob) type in mysql. After specifying 'Binary' with a length argument, i.e. Binary(64000000) for 64Mb.
1.5.2 2008-10-08 text data type in database
base64 is the package offering encoding binary into text.:
snp_region_plot = SNPRegionPlot.get(1)
import base64
outf = open('/tmp/snp_region_plot_1.png', 'wb')
outf.write(base64.b64decode(snp_region_plot.img_data))
outf.close()
base64.b64encode is the correspondent of base64.b64decode.
1.5.3 2009-6-2 embed select in the where clause
Tested in mysql:
select * from phenotype_avg where ecotype_id not in (select ecotype_id from view_call where call_method_id=32); delete from phenotype_avg where ecotype_id not in (select ecotype_id from view_call where call_method_id=32);
2 PostgreSQL
2.1 management (copied from /log/log_05/node77.html 2007-05-11)
Table name length is limited to 32 characters. Any longer than that will be truncated to 32. (10-13-05, it seems larger than 32, 38 is fine.)
Dot(.) could not be used in table name.
Dump a schema and restore it. pg_dump -n schemaname -O dbname > outputfile, psql dbname < outputfile.
(10-01-05) Change the default location of POSTGRES_DATA. 1. Change the variable in /etc/postgresql/postmaster.conf. 2. symlink the default directory to a new directory. Run initdb to the new directory ahead.
(10-01-05) ident authentication maps the client's OS username to the server's database username. But when trying to connect to database server from the client, the username to connect should be the server's database username, not the client's username. i.e. psql -h gan.usc.edu -U feipan mdb; (the client's username is yh). The server's pg_ident.conf should have an entry to map yh to feipan.
(10-11-05) postgresql's own md5, password.. authentication is separate from the Unix system. But pam method can enable the unix system authentication.
- (10-11-05) ssl connection.
- Generate server.key and server.crt in the data directory, not the /etc/postgresql.
- Ownership goes to the server user. server.key's permission should be safe(600).
- enable ssl in postgresql.conf.
- edit pg_hba.conf and restart it.
- ssl connection uses the same port as the non-ssl.
- (optional) root.crt is optional. Postgresql will authenticate the client if it's present. If it's not present, client certificates are not checked.
- The change made to *.crt or *.key comes to effect only after the server is restarted.
2.2 substitute the old table with a new table, but the same name(2006-08-28)
- the first method you think of is "alter table xxx rename to xxx" and then "create table xxx...". But this usually doesn't work. When the table has affiliated sequence, primary key, ..., those affiliated stuff's names are not changed. And "create table xxx ..." causes conflict.
- So the correct way is create a table with different name but same structure and transfer the records to the new table, 'INSERT INTO prom_seq_bug_08_28_06 SELECT * from prom_seq;' and then delete the old table, create a new table with same name.
2.3 2007-03-20 pattern matching via regular expression:
'~' means LIKE. '*' means case-insensitive. D is non-digital. one more (back-slash) is used to escape.:
SELECT * from strain_info where acc ~*'Yng-3\\D';
2.4 2007-05-11 create user in version 8.2
super user password 'secret' has to be put at last.:
CREATE ROLE username with LOGIN CREATEDB CREATEUSER ENCRYPTED password 'secret';
2008-02-27 normal user with select on certain tables.:
create user username; -- =create role username with LOGIN grant select on gene.gene to username; -- select can't be granted to schema. only grant usage on schema gene to username. But usage!=select.
2.5 2007-05-11 migrate graphdb
dump the database:
pg_dump -O graphdb |gzip /backup/zhoudb_graphdb.gz
create an empty database.
04/17/08 The original db is in SQL_ASCII encoding. The default in createdb has become UTF8 which causes `` invalid byte sequence for encoding "UTF8": 0xa0`` error (the whole table becomes empty.) when the old db is restored in UTF8 db. db template1 has to be disconnected for createdb to run.:
createdb -E SQL_ASCII graphdb
create the script language. 04/17/08 this is not necessary. The dump file contains such a command.:
createlang plpythonu graphdb
re-construct the database. 04/17/08 & after > is used to merge stdout and stderr.:
gunzip -c /var/lib/postgresql/zhoudb_graphdb.gz |psql graphdb >& /tmp/std
output of above command: 04/17/08 log
2008-02-03 standard readme table with automatic updates on user and date:
create table readme(
id serial primary key,
title varchar,
description varchar,
created_by varchar default current_user,
updated_by varchar,
date_created timestamp WITH TIME ZONE default current_timestamp,
date_updated TIMESTAMP WITH TIME ZONE
);
create function insert_readme() returns trigger as '
begin
if new.created_by is null then
new.created_by := current_user;
end if;
if new.date_created is null then
new.date_created := current_timestamp;
end if;
return new;
end;
'
language plpgsql;
create trigger insert_readme before insert on readme
for each row execute procedure insert_readme();
create function update_readme() returns trigger as '
begin
new.date_updated := current_timestamp;
new.updated_by := current_user;
return new;
end;
'
language plpgsql;
create trigger update_readme before update on readme
for each row execute procedure update_readme();
2.6 2008-11-06 add a forein key column to a table
syntax is similar to mysql:
alter table job add how_job_ended_id varchar(512) references job_state (short_name) on delete set null on update cascade;
2.7 2009-9-16 change postgresql character encoding
copied from /research/variation/log-2007-04.
change the postgresql encoding from 'UTF8' to 'LATIN10' ('MULE_INTERNAL' can't be set because ERROR: conversion between mule_internal and UTF8 is not supported):
graphdb=# set client_encoding TO latin4; SET graphdb=# set client_encoding TO latin10; graphdb=# show client_encoding ; client_encoding ----------------- latin10 (1 row)
3 MySQL
3.1 2009-10-25 database encoding (character set)
The default character set (latin1/latin1_swedish_ci) is not widely used, which causes problem when data is transmitted across files and databases. Output of show variables looks like:
+--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | latin1 | | character_set_system | utf8 | | collation_connection | latin1_swedish_ci | | collation_database | latin1_swedish_ci | | collation_server | latin1_swedish_ci | +--------------------------+-------------------+
To change the default character set, add following to my.cnf:
[client] default-character-set = utf8 [mysqld] default-character-set = utf8
Output of show variables would look like:
+---------------------------------+-----------------------------------+ | Variable_name | Value | +---------------------------------+-----------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | latin1 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | | collation_connection | utf8_general_ci | | collation_database | latin1_swedish_ci | | collation_server | utf8_general_ci |
Sometimes, character_set_database and collation_database would turn into utf8 in the beginning and then turn back into latin1. Maybe because there are still some tables in character set latin1.
3.2 2007-04-26 set the pager for the mysql client, '-p' is to let the server ask for password.
mysql --pager=less -p
3.3 2007-04-26 starting commands in mysql client
show databases;
use database_name;
show tables;
desc table_name;
pager less;
3.4 2009-9-20 stock (149SNP) database
3.4.1 2007-06-11 dump and restore stock (149SNP) database
3.4.1.1 2007-10-21 I. add table person
This table has to be done first because other tables have foreign keys pointing to it.
- mysql -h natural.uchicago.edu -u iamhere -p stock -e "select id, title, SURNAME, FIRSTNAME, EMAIL, '', '', 0, DONOR from person" > /tmp/uchicago.mysql.stock.db.person
- remove the header(1st line) in /tmp/uchicago.mysql.stock.db.person
- mysql>create database stock;
- create table person using the scheme in variation/src/mysql.sql
- mysql>load data infile '/tmp/uchicago.mysql.stock.db.person' into table person;
3.4.1.2 2007-06-11 II. dump and restore the rest
mysqldump -h natural.uchicago.edu -u iamhere -p stock --ignore-table=stock.person --skip-lock-tables > /tmp/uchicago.mysql.stock.db
table person has sensitive password information iamhere doesn't have privilege to view. lock-tables is also not a privilege for iamhere.
open the dump file, /tmp/uchicago.mysql.stock.db, with vi and change data type to make new table addition by StockDB.py easier:
replace all 'unsigned' with '': ``g/unsigned/s///gc`` replace all 'tinyint' with 'integer': ``g/tinyint([0-9])/s//integer/gc`` replace all 'smallint' with 'integer': ``g/smallint([0-9])/s//integer/gc``
mysql stock </tmp/uchicago.mysql.stock.db
3.4.1.3 2008-08-11 III. further steps
alter table calls rename to calls_old to prepare for the run by Calls_BySeq2Calls.py
initialize more tables: ~/script/variation/src/StockDB.py -z papaya -u yh.
run variation/src/Calls_BySeq2Calls.py
add id 100000 into ecotype table based on previous stock data or https://dl324b-1.cmb.usc.edu/projects/hapmap/ticket/24
run variation/src/GroupDuplicateEcotype.py to link ecotypeid to tg_ecotypeid (truncate the 3 tables given in the program options if overhaul is needed).
run some manual updates in variation/src/mysql.sql to correct some tg_ecotypeid linking.
fill up qc_method, contaminant_type, by copying content from old version of stock db.
- insert into qc_method select * from stock20081217.qc_method;
- insert into contaminant_type select * from stock20081217.contaminant_type;
fill up country.
- alter table country add capital text;
- alter table country add latitude float;
- alter table country add longitude float;
- update country c1, stock20081217.country c2 set c1.capital=c2.capital, c1.latitude=c2.latitude, c1.longitude=c2.longitude where c1.name=c2.name;
2009-3-30 add more foreign keys:
alter table ecotype add foreign key (organismid) references organism(id) on delete cascade on update cascade; alter table ecotype add foreign key (tripid) references trip(id) on delete cascade on update cascade; #optional, all tripid null. alter table ecotype add foreign key (donorid) references person(id) on delete cascade on update cascade; alter table address add foreign key (countryid) references country(id) on delete cascade on update cascade; alter table batch_ecotype add foreign key (ecotypeid) references ecotype(id) on delete cascade on update cascade;
2009-3-30 change table site_trip:
ALTER TABLE site_trip ENGINE = InnoDB; alter table site_trip add foreign key (tripid) references trip(id) on delete cascade on update cascade; alter table site_trip add foreign key (siteid) references site(id) on delete cascade on update cascade; #foreign key error
table site_trip and site have some inconsistency. some siteid``s are not in table ``site, which caused the foreign key to fail.
3.4.1.4 2008-08-11 notes
- Type of the primary keys in almost all tables (i didn't check exhaustively) is integer unsigned, which is an anomaly. Any foreign key which points to them in new tables have to be of that unsigned type.
- a few mysiam type table tables still exist.
- lots of hidden foreign relationship haven't been clarified.
3.4.2 2009-9-20 update table ecotype to reflect changes made in uchicago's ecotype
Apart from latitude & longitude changes of 72 ecotypes, numerous (~700) other changes were made in uchicago's ecotype table, like collectiondate and etc.
create a temporary ecotype table to hold all data from uchicago's ecotype
substitute everything from the old ecotype with counterparts from the temp table. mysql records the number of changes. The syntax was generated by python based on the fields.:
update ecotype e1, ecotype_uchicago e2 set e1.DONORID=e2.DONORID, e1.COLLECTORID=e2.COLLECTORID, e1.SITEID=e2.SITEID, e1.TRIPID=e2.TRIPID, e1.ORGANISMID=e2.ORGANISMID, e1.CROSSID=e2.CROSSID, e1.NAME=e2.NAME, e1.ALIAS=e2.ALIAS, e1.DNANAME=e2.DNANAME, e1.description=e2.description, e1.BARCODE=e2.BARCODE, e1.STOCKPARENT=e2.STOCKPARENT, e1.NATIVENAME=e2.NATIVENAME, e1.COLLECTIONDATE=e2.COLLECTIONDATE, e1.LATITUDE=e2.LATITUDE, e1.LONGITUDE=e2.LONGITUDE, e1.LOCATIONQUALITY=e2.LOCATIONQUALITY, e1.ELEVATION=e2.ELEVATION, e1.DNASTATUS=e2.DNASTATUS, e1.BULKSTATUS=e2.BULKSTATUS, e1.BULKDATE=e2.BULKDATE, e1.LABDERIVED=e2.LABDERIVED, e1.INCOMPLETEPLEX=e2.INCOMPLETEPLEX where e1.id=e2.id;
one strange thing starting to be noticed is that master-slave (denoted as ->) is not transitive. In a scenario, Machine1->Machine2->M3, changes in Machine1 get only passed onto M2 and M3 doesn't get any change.
3.4.3 2009-10-19 set the minimum and standard deviation of each phenotype
It's used in the log-transformation, which makes sure no negative value would be fed into the logarithm formula.
After values are put into table phenotype_avg, run this in mysql client:
update phenotype_method pm, (select method_id, min(value) as min_value, stddev(value) as stddev from phenotype_avg where method_id >=340 group by method_id) as pa set pm.min_value=pa.min_value, pm.stddev=pa.stddev where pm.id=pa.method_id;
3.5 2007-06-11 user/privilege management
mysql>GRANT ALL PRIVILEGES ON *.* TO 'crocea'@'localhost' identified by 'password';
'CREATE USER' syntax would have the same effect but still needs 'GRANT' to get all privileges. % could be used to replace localhost to specify any host.
mysql>FLUSH PRIVILEGES; tells the server to reload the grant table
Privilege types include USAGE, SELECT, etc. USAGE is like nothing, just account created.
The logic of mysql user management is two tables, mysql.user and mysql.db. Each user is identified by its name and hostname (from where the user is allowed to access database). Associating hostname with a user account is not a smart idea. This causes password entering every time a new hostname happens to a user.
3.5.1 2008-04-09 SUPER privilege
according to http://dev.mysql.com/doc/refman/5.0/en/grant.html. SUPER privilege is one of the administrative privileges that can only be granted globally (using ON *.* syntax). Mysteriously, SUPER is needed for some operation even ALL PRIVILEGES is already granted. Apparently they are somehow different.
One example is a program inserts into a table where the user is super user (not sure ALL PRIVILEGES or SUPER is also included) on a master db. The insertion would automatically trigger a field created_by filled by a username (USER() in mysql). This trigger breaks down on the slave machine, which sometimes causes the master insertion to break down. sometimes only cause the master-slave SQL connection to break down.
Usually the error looks like:
ERROR 1227 (42000): Access denied; you need the SUPER privilege for this operation
- 2008-04-12 bug cleared
- The db on master (papaya) is restored thru a dump of a namesake db from the slave. The dump preserved the owner (field Definer in show triggers) of triggers, who are not users on the master and thus have no SUPER privilege. It seems SUPER privilege is required for the owner of triggers. So grant super on *.* to 'user'@'any.host' solves the problem.
3.5.3 2008-04-11 remove user password
directly modifying table mysql.user:
update mysql.user set Password=NULL where Host='localhost' and User='jeffrey';
3.5.4 2008-04-24 add specific privilege to a user
grant insert on dbname.* to 'crocea'@'localhost' grants the privilege for a particular database. If 'crocea'@'localhost' already has an entry in mysql.user, it won't create a new one and keep the old password. Otherwise, it'll insert an entry into mysql.user with no password. It changes mysql.db for sure.
directly modifying table mysql.user to change privilege for all databases:
update mysql.user set insert_priv='Y' where Host='localhost' and User='jeffrey';
3.5.5 2008-08-14 host-based privilege
One thing to note is that mysql is very strict about hostname. For example, dl324b-1 and dl324b-1.cmb.usc.edu are regarded differently, let alone IP adress. I suspect the underlying authentication system is matching the client's reported hostname to column host in mysql.user.
3.6 2007-06-11 enable network access
configure /etc/mysql/my.cnf, change 'bind-address = 127.0.0.1' to 'bind-address = your-machine-ip'
3.7 2005-12-10 copy table to file
to client file (more useful generally):
mysql -h db.cisred.org -u anonymous -e "select * from cisred_Hsap_2.features" > /tmp/yuhuang/features
2007-06-11 copy table to server file:
select * from cisred_Hsap_2.features into outfile '/tmp/yuhuang/features';
3.8 2007-06-11 load data into table from a file (copy in postgresql)
examples:
mysql> load data infile '/tmp/person_reshuffled_for_table' into table person CHARACTER SET utf8; mysql> load data infile '/tmp/magnus_192.csv' into table magnus_192 FIELDS terminated by ',';
2008-02-12 \N is taken as NULL data type, specified by 'FIELDS ESCAPED BY' of 'load data infile' syntax, which only supports one-char separator and tests show it fails to recognize multi-char separator, like NA.
2009-10-25 If the contents of the input file use a character set that differs from the default (which constantly falls back on the recalcitrant latin1), specify the character set of the file by using the CHARACTER SET clause. Omitting CHARACTER SET clause is generally ok unless the input file contains some non-English letters (like Löv-5). The database server would use the system variable character_set_database (which =``latin1``) to interpret the data and if the table to hold the data has a different character set, funny things would ensue.
3.9 2007-09-27 regular expression search
REGEXP or RLIKE, both are not case sensitive:
select * from ecotype where nativename rlike 'Col-.*';
3.10 2007-10-10 no 'full join' for mysql
- check http://dev.mysql.com/doc/refman/5.1/en/join.html. example::
- select distinct a.id,a.name,e.nativename from at.accession a left join ecotype e on e.nativename = a.name order by nativename, name;
3.11 2007-10-10 varchar syntax
datatype varchar has to have (M) attached to specify the maximum number of characters. like varchar(20). just 'varchar' won't work.
3.12 2008-01-09 transaction
http://dev.mysql.com/doc/refman/5.1/en/transactional-commands.html shows mysql could handle transaction. I tested it with creating a table, it didn't work.:
begin; xxxx; rollback;
2008-01-15 Transaction is only for the Innodb engine. Either step below transforms database into "INNODB":
- insert default-storage-engine=innodb into [mysqld] section of /etc/mysql/my.cnf
append engine=innodb to the end of create table syntax:
create table tmp (id integer) engine=innodb;
then begin; xxx; rollback; would start to work.
create table is not something that could be rolled back.
3.13 2008-01-09 table
3.13.1 2008-01-09 table engine
Engine InnoDB has transaction and foreign key capability.
to change a table engine:
ALTER TABLE phenotype ENGINE = InnoDB;
A few commands to ensure InnoDB environment:
SET AUTOCOMMIT = 0; SET storage_engine=INNODB;
However there are quite a few operations that can't be rolled back. check http://dev.mysql.com/doc/refman/5.0/en/cannot-roll-back.html and http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster-limitations-transactions.html.
these include data definition language (DDL) statements, such as
- create or drop databases
- those that create, drop, or alter tables or stored routines.
- TRUNCATE is not transactional when used on NDB tables.
- LOAD DATA statements. LOAD DATA INFILE is not transactional when used on NDB tables.
3.13.2 2008-05-04 get more details/description about a table
show column name/types:
desc mytable;
get more information about tables in 'mydatabase', engine type, etc:
select * from information_schema.tables where table_schema='mydatabase'; show table status; --execute this in a database, get same stuff as above
show all the indexes of a table:
SHOW INDEXES FROM mytable;
show all the triggers:
show triggers;
show complete information of a table:
show create table mytable;
show the last foreign key error:
SHOW ENGINE INNODB STATUS\G
3.13.3 2008-05-07 table name case sensitivity
according to http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html, table aliases are case sensitive on Unix, but not so on Windows or Mac OS X.
more quotes
How table and database names are stored on disk and used in MySQL is affected by the lower_case_table_names system variable, which you can set when starting mysqld. lower_case_table_names can take the values shown in the following table. On Unix, the default value of lower_case_table_names is 0. On Windows the default value is 1. On Mac OS X, the default value is 2.
If you plan to set the lower_case_table_names system variable to 1 on Unix, you must first convert your old database and table names to lowercase before stopping mysqld and restarting it with the new variable setting.
3.13.4 2008-07-15 syntax to add a unique constraint
don't forget to put parenthesis around the column name.:
alter table gene_list_type add UNIQUE (short_name);
drop a unique key. a user posted a comment in http://dev.mysql.com/doc/refman/5.0/en/alter-table.html and claimed that you have to drop foreign keys first if columns in unique key are also used as foreign key. That is not true.:
alter table candidate_gene_rank_sum_test_result drop key results_method_id;
This is special because results_method_id is also the name for another column. It is the name of the unique key UNIQUE KEY results_method_id (results_method_id, list_type_id).
3.13.5 2008-07-15 change table column
If the column has a foreign key or a unique constraint associated with, those keys have to be dropped before dropping the column or change the type of the column. Watch. Syntax to drop foreign key is different from dropping unique constraint.
For example, a table has a foreign key on column results_by_gene_id. I wanna rename results_by_gene_id to results_id.:
PRIMARY KEY (`id`), KEY `ix_candidate_gene_rank_sum_test_result_list_type_id` (`list_type_id`), KEY `results_by_gene_id` (`results_by_gene_id`), CONSTRAINT `candidate_gene_rank_sum_test_rbg_ibfk_1` FOREIGN KEY (`results_by_gene_id`) REFERENCES `results_by_gene` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `candidate_gene_rank_sum_test_result_list_type_id_fk` FOREIGN KEY (`list_type_id`) REFERENCES `candidate_gene_list_type` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=529437 DEFAULT CHARSET=latin1 |
drop foreign key:
alter table candidate_gene_rank_sum_test_rbg drop foreign key candidate_gene_rank_sum_test_rbg_ibfk_1;
drop index:
alter table candidate_gene_rank_sum_test_rbg drop index results_by_gene_id;
rename column results_by_gene_id:
alter table candidate_gene_rank_sum_test_rbg CHANGE results_by_gene_id results_id integer;
add the foreign key back:
alter table candidate_gene_rank_sum_test_rbg add foreign key (results_id) references results_by_gene(id) on delete cascade on update cascade;
In the end, i have to say mysql sucks. postgresql never requires these tedious procedures.
3.14 2008-01-28 TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause
There can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause. So a plan to have both date_created and date_modified default to CURRENT_TIMESTAMP would fail. So it's now like this:
... date_created timestamp default 0, date_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, ...
3.15 2008-02-03 standard mysql readme table with automatic updates on user and date
check this:
create table readme(
id integer auto_increment primary key,
title varchar(2000),
description varchar(60000),
created_by varchar(200),
updated_by varchar(200),
date_created timestamp default CURRENT_TIMESTAMP,
date_updated TIMESTAMP default 0
);
DELIMITER | -- change the delimiter ';' to '|' because ';' is used as part of one statement.
CREATE TRIGGER before_insert_readme BEFORE INSERT ON readme
FOR EACH ROW BEGIN
if NEW.created_by is null then
set NEW.created_by = USER();
end if;
if NEW.date_created is null then
set NEW.date_created = CURRENT_TIMESTAMP();
end if;
END;
|
CREATE TRIGGER before_update_readme BEFORE UPDATE ON readme
FOR EACH ROW BEGIN
set NEW.updated_by = USER();
set NEW.date_updated = CURRENT_TIMESTAMP();
END;
|
DELIMITER ;
3.15.1 2008-04-11 the automatic trigger on user doesn't work very well between master and slave.
When the data is inserted thru MySQL module in python, the slave table messes up the created_by field, fills it in with some random codes.
When the data is updated thru mysql console connected to the master, the updated_by will have different usernames recorded.
It might be that master transmitted a user id(a number) to slave and slave translates according to its own user table.
3.16 2008-01-28 replicate mysql (master-slave)
create a user for replication on the master:
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.domain.com' IDENTIFIED BY 'secret_password';
setting the replication master configuration:
[mysqld] log-bin=mysql-bin server-id=1
setting the replication slave configuration
[mysqld] server-id=2
obtaining the master replication information on the master:
mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | mysql-bin.003 | 73 | test | manual,mysql | +---------------+----------+--------------+------------------+
unlock tables will release all locks imposed by `` FLUSH TABLES WITH READ LOCK``.
Creating a Data Snapshot Using mysqldump on the master:
mysql> FLUSH TABLES WITH READ LOCK; mysqldump -h master_host --lock-all-tables -u username -p --databases DB1 DB2 >/tmp/master.dump.db
create a snapshot of master data on slave
startup the slave without replication started by using the --skip-slave option (actually just /etc/init.d/mysql restart will do as far as master setup isn't put into my.cnf.):
sudo /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/var/run/mysqld/mysqld.pid \ --skip-external-locking --port=3306 --socket=/var/run/mysqld/mysqld.sock --skip-slave-start
Import the dump file:
mysql < /tmp/master.dump.db
Setting the Master Configuration on the Slave:
mysql> CHANGE MASTER TO MASTER_HOST='master_hostname', MASTER_USER='repl', MASTER_PASSWORD='secret',MASTER_LOG_FILE='mysql-bin.003', MASTER_LOG_POS=73;
start the slave:
mysql> START SLAVE;
Once a slave is replicating, you can find in its data directory one file named master.info and another named relay-log.info. The slave uses these two files to keep track of how much of the master's binary log it has processed.
add following to my.cnf on the slave:
report-host=slave_hostname #2008-01-29 otherwise the 'show slave hosts' on master wouldn't show the slave relay-log=/var/run/mysqld/mysqld-relay-bin #2008-01-29 suggested in /var/log/syslog
Restart the slave mysql daemon:
sudo /etc/init.d/mysql start
3.16.1 2008-02-03 Trouble-shooting
check slave status, SHOW SLAVE STATUS\G, make sure both Slave_IO_Running and Slave_SQL_Running are Yes.
if stopped by error, skip errors by SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; and start the slave again, start slave;
COMMENT: Trigger has its own definer whose privilege is checked before it's executed. master and slave having different users cause the error. It doesn't solve problem entirely by creating the trigger definer on the slave.
2008-02-07 can't start slave. errors
ERROR 1201 (HY000): Could not initialize master info structure; more error messages can be found in the MySQL error log
turn on log_err in my.cnf and see more:
080207 22:49:52 [ERROR] Failed to open the relay log '/var/run/mysqld/mysqld-relay-bin.000164' (relay_log_pos 235) 080207 22:49:52 [ERROR] Could not find target log during relay log initialization 080207 22:49:52 [ERROR] Failed to initialize the master info structure
solution: that relay-bin file is missing. so you edit /var/lib/mysql/relay-log.info and point it to existing relay-bin in /var/run/mysqld/. And leave the log_pos (2nd line) empty. It'll fix in the next daemon restart.
3.16.2 2008-08-14 master-slave thru SSL
Master setup is same as normal mysql server ssl setup (check a section below).
Setup slave like this:
CHANGE MASTER TO \
MASTER_HOST='master_hostname', \
MASTER_USER='replicate', \
MASTER_PASSWORD='password', \
MASTER_SSL=1, \
MASTER_LOG_FILE='mysql-bin.000477', \
MASTER_LOG_POS=947,\
MASTER_SSL_CA = 'ca_file_name', \
MASTER_SSL_CAPATH = 'ca_directory_name', \
MASTER_SSL_CERT = 'cert_file_name', \
MASTER_SSL_KEY = 'key_file_name';
MASTER_SSL_CA is required. MASTER_SSL_CAPATH, MASTER_SSL_CERT, ``MASTER_SSL_KEY are optional. Could omit them or give them ''.
If REQUIRE SSL is not in the grant replication slave ..., then MASTER_SSL_CA could be omitted as well. MASTER_SSL=1 or MASTER_SSL=0 doesn't matter in this situation.
3.17 2008-02-18 foreign key
Both tables have to be InnoDB type.
The foreign key column and its referenced key must be of same type.
- The size and sign of integer types must be the same.
- The length of string types need not be the same.
- For non-binary (character) string columns, the character set and collation must be the same.
foreign key has to be specified. Just References doesn't work. Constraint is optional.:
create table array_info( id integer auto_increment primary key, filename varchar(1000), description varchar(2000), strain_id integer not null, CONSTRAINT array_info_strain_id_fk_constraint foreign key (strain_id) references strain_info(id) on delete cascade on update cascade )engine=INNODB;
SHOW CREATE TABLE tbl_name; or SHOW TABLE STATUS FROM db_name LIKE 'tbl_name'; display the foreign key constraint.
SET storage_engine=INNODB; set the storage engine for this session.
3.17.1 2008-08-08 add a foreign key
syntax:
alter table tg_ecotypeid add foreign key (tg_ecotypeid) references ecotype(id) on delete restrict on update cascade;
3.18 2008-04-09 rename database
MySQL doesn't have a command for that (while postgresql has ALTER DATABASE name RENAME TO newname.)
People suggest (http://www.delphifaq.com/faq/databases/mysql/f574.shtml) to manually rename the db directory name in datadir (like /var/lib/mysql) while db is shut down. It causes mysql unable to find the tables under the renamed db and conflict with a second db with same db/table name as the old name of the 1st db.
The solution:
dump the old one out:
mysqldump -h hostname -u username -p db_name > /tmp/db_name.dump.sql
drop the old database and create a new database in mysql client:
mysql> drop database db_name; mysql> create database new_db_name;
restore the database under the new db name:
mysql new_db_name < /tmp/db_name.dump.sql
3.19 2008-08-08 poking database status
3.19.1 2008-04-21 show connection
SHOW PROCESSLIST;
2008-05-21 kill a thread (connection/query), THREAD_ID is id in the table returned by the command above.:
kill THREAD_ID
3.19.2 2007-06-11 see the warnings given out by the server
mysql> show warnings;
3.19.3 2008-08-08 check specific variable
mysql> SHOW VARIABLES;
mysql> SHOW VARIABLES LIKE 'have_ssl';
mysql> SHOW STATUS LIKE 'Ssl_cipher';
mysql> \s
mysql> SHOW STATUS
3.19.4 2008-08-11 explain error codes
shell command perror:
localhost:~ root# perror 150 MySQL error code 150: Foreign key constraint is incorrectly formed
3.19.6 2009-7-30 master/slave status
syntax:
mysql> SHOW MASTER STATUS; mysql> SHOW slave STATUS;
replace ; with \G to see in vertical format.
3.21 2008-08-14 mysql SSL connection
3.21.1 server
http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html
create CA certificates:
# Create CA certificate shell> openssl genrsa 2048 > ca-key.pem shell> openssl req -new -x509 -nodes -days 1000 \ -key ca-key.pem > ca-cert.pemCreate server certificate:
shell> openssl req -newkey rsa:2048 -days 1000 \ -nodes -keyout server-key.pem > server-req.pem shell> openssl x509 -req -in server-req.pem -days 1000 \ -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pemmy.cnf. ssl-cipher is not necessary. without this, mysqld default will use DHE-RSA-AES256-SHA.
[mysqld] ssl-ca=$DIR/cacert.pem ssl-cert=$DIR/server-cert.pem ssl-key=$DIR/server-key.pem
restart server. Watch file permission. These pem files have to be readable to the user id who runs the mysqld server.
3.21.2 client
http://dev.mysql.com/doc/refman/5.0/en/secure-using-ssl.html
If the account has no special SSL requirements or was created using a GRANT statement that includes the REQUIRE SSL option, a client can connect securely by using just the --ssl-ca option. ssl-ca can also be set in [client] section of my.cnf.:
shell> mysql --ssl-ca=cacert.pem
To require that a client certificate also be specified, create the account using the REQUIRE X509 option. Then the client must also specify the proper client key and certificate files or the server will reject the connection. The options could also be set in [client] section of my.cnf.
shell> mysql --ssl-ca=cacert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
Note: To generate client certificates, check http://dev.mysql.com/doc/refman/5.0/en/secure-create-certs.html:
# Create client certificate
shell> openssl req -newkey rsa:2048 -days 1000 \
-nodes -keyout client-key.pem > client-req.pem
shell> openssl x509 -req -in client-req.pem -days 1000 \
-CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem
3.22 2009-5-19 Procedure
Procedure in MySQL is basically a function. One tricky thing is the delimiter cuz ; is used in procedure for a different purpose. Check this:
DELIMITER | CREATE PROCEDURE dowhile() BEGIN DECLARE v1 INT DEFAULT 1; WHILE v1 <93 DO SET v1 = v1 + 1; insert into accession2call_method VALUES (1, v1); END WHILE; END| call dowhile()| drop procedure dowhile| delimiter;