Archive for the ‘MySQL’ Category
Lowercase Table Names
A student posed the question about why table names are case sensitive. That’s because case sensitive table names are the default installation, as qualified in the MySQL documentation. You can verify that with the following query:
SELECT CASE WHEN @@lower_case_table_names = 1 THEN 'Case insensitive tables' ELSE 'Case sensitive tables.' END AS "Table Name Status"; |
The default value returned on Linux is:
+------------------------+ | Table Name Status | +------------------------+ | Case sensitive tables. | +------------------------+ 1 row in set (0.00 sec) |
The default value for the lower_case_table_names
value on the Windows OS is 1
not 0
because you can inadvertently create a lowercase and case sensitive table when you write an INSERT
statement and use a lowercase table name. I’ve provided that detail in a reply comment to this blog post.
You can change the default by adding the following parameter in the my.cnf
file on Linux or the my.ini
file on Windows:
# Make all tables case insensitive. lower_case_table_names=1 |
This lets you enter tables in upper or mixed case, and stores them in the data catalog as lowercase table names.
Querying InnoDB Tables
Somebody ran into the following error message trying to query the innodb_sys_foreign
and innodb_sys_foreign_cols
tables from the information_schema
database:
ERROR 1227 (42000): Access denied; you need (at least one of) the PROCESS privilege(s) for this operation |
It’s easy to fix the error, except you must grant the PROCESS
privilege. It’s a global privilege and it should only be granted to super users. You grant the privilege global PROCESS
privilege to the student
user with the following command:
GRANT PROCESS ON *.* TO student; |
Then, you can run this query to resolve foreign keys to their referenced primary key column values:
SELECT SUBSTRING_INDEX(f.id,'/',-1) AS constraint_name , CONCAT(SUBSTRING_INDEX(for_name,'/',-1),'.',SUBSTRING_INDEX(for_col_name,'/',-1)) AS foreign_key_column , CONCAT(SUBSTRING_INDEX(ref_name,'/',-1),'.',SUBSTRING_INDEX(ref_col_name,'/',-1)) AS primary_key_column FROM innodb_sys_foreign f INNER JOIN innodb_sys_foreign_cols fc ON f.id = fc.id WHERE SUBSTRING_INDEX(f.for_name,'/',-1) = 'system_user_lab' ORDER BY CONCAT(SUBSTRING_INDEX(for_name,'/',-1),'.',SUBSTRING_INDEX(for_col_name,'/',-1)) , CONCAT(SUBSTRING_INDEX(ref_name,'/',-1),'.',SUBSTRING_INDEX(ref_col_name,'/',-1)); |
It returns the following:
+---------------------+--------------------------------------+------------------------------------+ | constraint_name | foreign_key_column | primary_key_column | +---------------------+--------------------------------------+------------------------------------+ | system_user_lab_fk1 | system_user_lab.created_by | system_user_lab.system_user_id | | system_user_lab_fk2 | system_user_lab.last_updated_by | system_user_lab.system_user_id | | system_user_lab_fk3 | system_user_lab.system_user_group_id | common_lookup_lab.common_lookup_id | | system_user_lab_fk4 | system_user_lab.system_user_type | common_lookup_lab.common_lookup_id | +---------------------+--------------------------------------+------------------------------------+ 4 rows in set (0.00 sec) |
However, you can get the same information without granting the global PROCESS
privilege. You simply use the table_constraints
and key_column_usage
tables, like this:
SELECT tc.constraint_name , CONCAT(kcu.table_name,'.',kcu.column_name) AS foreign_key_column , CONCAT(kcu.referenced_table_name,'.',kcu.referenced_column_name) AS primary_key_column FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name AND tc.constraint_schema = kcu.constraint_schema WHERE tc.constraint_type = 'foreign key' AND tc.table_name = 'system_user_lab' ORDER BY tc.table_name , kcu.column_name; |
It prints the same output:
+---------------------+--------------------------------------+------------------------------------+ | constraint_name | foreign_key_column | primary_key_column | +---------------------+--------------------------------------+------------------------------------+ | system_user_lab_fk1 | system_user_lab.created_by | system_user_lab.system_user_id | | system_user_lab_fk2 | system_user_lab.last_updated_by | system_user_lab.system_user_id | | system_user_lab_fk3 | system_user_lab.system_user_group_id | common_lookup_lab.common_lookup_id | | system_user_lab_fk4 | system_user_lab.system_user_type | common_lookup_lab.common_lookup_id | +---------------------+--------------------------------------+------------------------------------+ 4 rows in set (0.00 sec) |
Hope this helps.
MySQL Non-unique Indexes
Somebody wanted to know how to find any non-unique indexes in information_schema
of the MySQL. The query takes a session variable with the table name and returns the non-unique indexes by column names. It uses a correlated subquery to exclude the table constraints. A similar query lets you find unique indexes in MySQL. Both queries are in this post.
You set the session variable like this:
SET @sv_table_name := 'member_lab'; |
You can query the indexes result with the following query:
SELECT s.table_name , s.index_name , s.seq_in_index , s.column_name FROM information_schema.statistics s WHERE s.table_name = @sv_table_name AND s.non_unique = TRUE AND NOT EXISTS (SELECT null FROM information_schema.table_constraints tc WHERE s.table_name = tc.table_name AND s.index_name = tc.constraint_name) ORDER BY s.table_name , s.seq_in_index; |
You can also reverse the logic and exclude implicit unique indexes on auto incrementing columns, like
SELECT s.table_name , s.index_name , s.seq_in_index , s.column_name FROM information_schema.statistics s WHERE s.table_name = @sv_table_name AND s.non_unique = FALSE AND NOT s.index_name = 'primary' AND EXISTS (SELECT null FROM information_schema.table_constraints tc WHERE s.table_name = tc.table_name AND s.index_name = tc.constraint_name) ORDER BY s.index_name , s.seq_in_index; |
Hope this helps those trying to find non-unique indexes for a table in MySQL.
Popular PHP Frameworks
My students often ask me about popular PHP frameworks and MySQL approaches. I wish a PHP framework choice was as clear as a JavaScript framework, like AngularJS. Unfortunately, PHP frameworks aren’t that clear cut.
It seems that the most popular PHP frameworks are: Laravel (1st), Phalcon (2nd), and Symphony2 (3rd). I found the following graphic (from December 2013) that highlights popularity by percentage of the market (though I can’t guarantee its accuracy). As far as jobs go, on Dice.com only Laravel had more than 3 positions referring to the framework by name. There were actually 42 PHP developer positions that mention Laravel out of 2,115 PHP developer positions. So, it seems learning a specific framework for PHP doesn’t yet have much market appeal.
While learning the basics of PHP are generic, frameworks expedite process and control pattern implementation. My suggestion to students is to target three to five employers that use a specific framework and start learning how to use the framework. I’d like to get opinions from those in the field whether this is the best advice.
As to MySQL, I suggest they learn native Mysqli and MySQL PDO. Any other suggestions on that from readers? Thanks as always.
Using MySQL Workbench
I’ve been setting up a simplified lab environment to let my students learn use in class. This added content will show them how to do reverse engineering with MySQL Workbench.
It’s a complete Fedora image with MySQL and Oracle Database 11g for the course. The uncompressed image is 14GB and the compressed image is 5.3GB. I chose Fedora because it’s the smallest open source image that supports both environments, and Fedora is the closest to Red Hat and Oracle Unbreakable Linux. I’m inclined to make the instance available generally but haven’t figured out the best way to do that.
Here are the new instructions I’m adding and if you have any input leave it as a comment. 😉
You connect as the student
user, which puts you in the /home/student
directory. Once connected to the Fedora OS, you open a Terminal session by clicking on Activities in the upper right hand corner, and then you type terminal
in the search box. When you’re in the Terminal session, use the following command to verify that the apply_mysql_lab1.sql
file is correct:
cat Data/cit225/mysql/lab1/apply_mysql_lab1.sql |
It should display the following commands:
\. /home/student/Data/cit225/mysql/lib/cleanup.sql \. /home/student/Data/cit225/mysql/lib/create_mysql_store_ri.sql \. /home/student/Data/cit225/mysql/lib/seed_mysql_store_ri.sql |
You can run the apply_mysql_lab1.sql
to create the tables in the studentdb
database, and seed them with data. Assuming you’re in the same /home/student
directory, you connect to the studentdb
database with the following syntax:
mysql -ustudent -pstudent studentdb |
or, more securely:
mysql -ustudent studentdb -p |
Having connected to the studentdb
database, you can run the following command:
\. /home/student/Data/cit225/mysql/lab1/apply_mysql_lab1.sql |
It creates a Video store image and seeds it with some basic data. You can use the show command to see the tables you’ve created, like:
show tables; |
It displays:
+---------------------+ | Tables_in_studentdb | +---------------------+ | address | | common_lookup | | contact | | contacts | | current_rental | | item | | member | | rental | | rental_item | | street_address | | system_user | | telephone | +---------------------+ 12 rows in set (0.00 sec) |
After successfully creating and seeding the studentdb
database, you can run MySQL Workbench by launching it from the search field (recommended). Alternatively, you can open it from a terminal session with the following command. Unfortunately, a command-line launch links the terminal and the MySQL Workbench processes and closing the terminal will close the MySQL Workbench.
mysql-workbench |
Here are the instructions for the lab with MySQL Workbench:
- The first displayed page of MySQL Workbench is the home page (click on it or any of the others to see the full size image). Click the ⊕ symbol to the right of the MySQL Workbench title.
- After clicking the the ⊕ symbol, it launches the Startup New Connection dialog. Enter a name for your new connection. I recommend you enter MySQLConnection.
- Click the Test Connection button to see if it works.
- When you click the Test Connection button, MySQL Workbench prompts you for a password. After entering a password and verifying the connection, click the OK button to test the connection.
- Click the OK button to continue.
- Click the gray highlighted MySQLConnection connection icon below the MySQL Connection title to launch the MySQL Workbench application.
- When you click the gray highlighted MySQLConnection connection icon, MySQL Workbench prompts you for a password. After entering a password and verifying the connection, click the OK button to connect to the MySQL Workbench application.
- The MySQL Workbench launches in the default view.
- Click on the Database menu option and then the Reverse Engineering… option, as shown in the illustration.
- This displays the Set Parameters for Connecting to a DBMS dialog. Click the Stored Connection list of values. Choose the MySQLConnection (if you used my suggestion) or the one you created from the list of values of the Stored Connection element. Click the Next button to continue.
- Enter the password and click the OK button to connect to the MySQL database.
- This is an in-progress display, it runs waiting for the password and until the step of the wizard completes.
- This dialog displays when the MySQL Workbench application connects to the database, retrieves a schema (database) list from the database management system, and checks the common server configuration issues. Click the Next button to move to the next step of the wizard.
- This Select Schemas to Reverse Engineer dialog displays any available schemas. You check the schemas that you want. Click the Next button to move to the next step of the wizard.
- Enter the password and click the OK button to connect to the MySQL database to retrieve objects from the database management system.
- This dialog displays when the MySQL Workbench application retrieves objects from the database. Click the Next button to move to the next step of the wizard.
- This dialog displays when the MySQL Workbench application retrieves objects from the schemata and checks the result. Click the Next button to move to the next step of the wizard.
- This dialog displays the tables, views, and routines to import. Click the Execute button to move to the next step of the wizard.
- This dialog displays the tables, views, and routines to import. Click the Execute button to move to the next step of the wizard.
- This dialog displays shows the reverse engineering objects and puts them in the object image. Click the Next button to move to the next step of the wizard.
- This dialog displays a summary of reverse engineering objects. Click the Close button to move to the next step of the wizard.
- The MySQL Model dialog displays after you complete the reverse engineering process. Click the EER Diagram icon or EER Diagram tab to see visual depiction of the database objects.
- The EER Diagram is equivalent to the EER Diagram tab. The Navigator displays the tables as blue rectangles. You can scroll through the Canvas Panel to work with the display of tables and views.
- The next image shows EER Diagram with the tables moved for display purposes. Sometimes there are too many relationship lines, MySQL Workbench lets you split the lines so they don’t clutter the diagram.
- The next image shows you the Property tab of EER Diagram. You should see that the drawSplit checkbox is checked, which suppresses the bottom-most relationship line from displaying in the EER from display on the Canvas Panel.
You can now save the MySQL Workbench file in the Lab 3 directory.
MySQL Workbench on Fedora
The early release of Fedora 20 disallowed installation of MySQL Workbench but the current version allows it. Almost like Tom Cruise’s Edge of Tomorrow without the drama. All you need to do is follow my earlier instructions for installing MySQL on Fedora 20. I’d check your kernel to know whether it’s supported. You can check that with this command:
<shell> uname -r |
My Fedora is at the following version:
3.14.8-200.fc20.x86_64 |
Then, you can install MySQL Workbench with yum
, like this:
<shell> sudo yum install mysql-workbench |
It generates the following log file, and if you have Oracle 11g XE installed you can ignore the mime-type error:
Loaded plugins: langpacks, refresh-packagekit Resolving Dependencies --> Running transaction check ---> Package mysql-workbench-community.x86_64 0:6.1.7-1.fc20 will be installed --> Processing Dependency: libzip.so.2()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: libvsqlitepp.so.3()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: libtinyxml.so.0()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: liblua-5.1.so()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: libgtkmm-2.4.so.1()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: libgdkmm-2.4.so.1()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Processing Dependency: libctemplate.so.2()(64bit) for package: mysql-workbench-community-6.1.7-1.fc20.x86_64 --> Running transaction check ---> Package compat-lua-libs.x86_64 0:5.1.5-1.fc20 will be installed ---> Package ctemplate.x86_64 0:2.2-5.fc20 will be installed ---> Package gtkmm24.x86_64 0:2.24.4-2.fc20 will be installed ---> Package libzip.x86_64 0:0.11.2-1.fc20 will be installed ---> Package tinyxml.x86_64 0:2.6.2-4.fc20 will be installed ---> Package vsqlite++.x86_64 0:0.3.13-3.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: mysql-workbench-community x86_64 6.1.7-1.fc20 mysql-tools-community 24 M Installing for dependencies: compat-lua-libs x86_64 5.1.5-1.fc20 updates 158 k ctemplate x86_64 2.2-5.fc20 fedora 174 k gtkmm24 x86_64 2.24.4-2.fc20 fedora 748 k libzip x86_64 0.11.2-1.fc20 updates 59 k tinyxml x86_64 2.6.2-4.fc20 updates 49 k vsqlite++ x86_64 0.3.13-3.fc20 updates 58 k Transaction Summary ================================================================================ Install 1 Package (+6 Dependent packages) Total download size: 26 M Installed size: 119 M Is this ok [y/d/N]: y Downloading packages: (1/7): compat-lua-libs-5.1.5-1.fc20.x86_64.rpm | 158 kB 00:01 (2/7): ctemplate-2.2-5.fc20.x86_64.rpm | 174 kB 00:01 (3/7): tinyxml-2.6.2-4.fc20.x86_64.rpm | 49 kB 00:00 (4/7): gtkmm24-2.24.4-2.fc20.x86_64.rpm | 748 kB 00:01 (5/7): vsqlite++-0.3.13-3.fc20.x86_64.rpm | 58 kB 00:00 (6/7): libzip-0.11.2-1.fc20.x86_64.rpm | 59 kB 00:02 (7/7): mysql-workbench-community-6.1.7-1.fc20.x86_64.rpm | 24 MB 00:08 -------------------------------------------------------------------------------- Total 2.9 MB/s | 26 MB 00:08 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : gtkmm24-2.24.4-2.fc20.x86_64 1/7 Installing : libzip-0.11.2-1.fc20.x86_64 2/7 Installing : vsqlite++-0.3.13-3.fc20.x86_64 3/7 Installing : ctemplate-2.2-5.fc20.x86_64 4/7 Installing : compat-lua-libs-5.1.5-1.fc20.x86_64 5/7 Installing : tinyxml-2.6.2-4.fc20.x86_64 6/7 Installing : mysql-workbench-community-6.1.7-1.fc20.x86_64 7/7 Error in file "/usr/share/applications/oraclexe-startdb.desktop": "Application/database" is an invalid MIME type ("Application" is an unregistered media type) Verifying : tinyxml-2.6.2-4.fc20.x86_64 1/7 Verifying : compat-lua-libs-5.1.5-1.fc20.x86_64 2/7 Verifying : ctemplate-2.2-5.fc20.x86_64 3/7 Verifying : vsqlite++-0.3.13-3.fc20.x86_64 4/7 Verifying : mysql-workbench-community-6.1.7-1.fc20.x86_64 5/7 Verifying : libzip-0.11.2-1.fc20.x86_64 6/7 Verifying : gtkmm24-2.24.4-2.fc20.x86_64 7/7 Installed: mysql-workbench-community.x86_64 0:6.1.7-1.fc20 Dependency Installed: compat-lua-libs.x86_64 0:5.1.5-1.fc20 ctemplate.x86_64 0:2.2-5.fc20 gtkmm24.x86_64 0:2.24.4-2.fc20 libzip.x86_64 0:0.11.2-1.fc20 tinyxml.x86_64 0:2.6.2-4.fc20 vsqlite++.x86_64 0:0.3.13-3.fc20 Complete! |
After successfully installing MySQL Workbench, you can launch it with the following command:
<shell> mysql-workbench |
It should launch the following MySQL Workbench home page (click on it to see the full size image):
MySQL Insert from Query
While working with an error that my students surfaced in the Oracle Database 12c, I blogged about the limit of using a subquery in an Oracle INSERT
statement, and I discovered something when retesting it in MySQL. It was a different limitation. I was also surprised when I didn’t find any mention of it through a Google search, but then I may just not have the right keywords.
The original test case uses a subquery to create a multiple row result set for an INSERT
statement. Unfortunately, I discovered that you can’t always embed a UNION
or UNION ALL
inside a subquery. At least, you can’t when you call the subquery inside an INSERT
statement. For example, let’s create a DESTINATION
table and then we’ll try to insert records with a query that fabricates a result set.
-- Drop the destination table. DROP TABLE IF EXISTS destination; -- Create the destination table. CREATE TABLE destination ( destination_id int unsigned , destination_name varchar(30)); |
Now let’s try the subquery:
1 2 3 4 | INSERT INTO destination ( SELECT 1,'Sample1' UNION ALL SELECT 2,'Sample2' ); |
It raises the following error message:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION ALL SELECT 2,'Sample2' )' at line 3 |
I wasn’t sure if I missed something. It turned out that I did. While you can put a subquery inside an INSERT
statement, you can’t embed it inside a set of parentheses when it contains a UNION ALL
set operator. Other statements work with or without parentheses.
1 2 3 4 | INSERT INTO destination SELECT 1,'Sample1' UNION ALL SELECT 2,'Sample2'; |
If somebody has any more to add, I look forward to reading it.
Toad Freeware Page
While I posted how to install Toad for MySQL Freeware five years ago, I’m always surprised how few people know about it there and consistently updated and improved. You can download Toad for MySQL Freeware or Toad Freeware for Oracle, SQL Server, Sybase, or IBM DB2 at this web site.
You can also download Toad Data Modeler Freeware Edition. Just two notes, while Toad for Oracle Freeware is an MSI file, Toad for MySQL Freeware is a zip file and limited to only a Windows install.
A/UX, NeXTSTEP, & OS X
One thing that gets tedious in the IT community and Oracle community is the penchant for Windows only solutions. While Microsoft does an excellent job in certain domains, I remain a loyal Apple customer. By the way, you can install Oracle Client software on Mac OS X and run SQL Developer against any Oracle Database server. You can even run MySQL Workbench and MySQL server natively on the Mac OS X platform, which creates a robust development platform and gives you more testing options with the MySQL monitor (the client software).
Notwithstanding, some Windows users appear to malign Apple and the Mac OS X on compatibility, but they don’t understand that it’s a derivative of the Research Unix, through BSD (Berkeley Software Distribution). This Unix lineage chart illustrates it well:
I’m probably loyal to Apple because in the early 1990’s I worked on Mac OS 6, Mac OS 7, A/UX, NeXTSTEP, and AIX/6000 (Version 3) while working at APL (American President Lines) in Oakland, California. Back then, my desktop was a pricey Macintosh Quadra 950 and today I work on a pricey Mac Pro desktop. The Mac Pro lets me use VMware virtualize development environments for Oracle Linux, Red Hat Enterprise Linux, Fedora, and as you might guess Windows 7/8. My question to those dyed in the wool Microsoft users is simple, why would you choose a single user OS like Windows over a multi-user OS like Mac OS X?
Deprecated mysqli Functions
mysqli
functions web page. There weren’t any deprecated by 5.5. Unfortuantely, there were six mysqli
functions deprecated in 5.3 and removed in 5.4. Unfortunately, many of my posted code examples use 5.2 or 5.3 where they would have worked. The deprecated mysqli
functions are:
mysqli_bind_param
mysqli_bind_result
mysqli_client_encoding
mysqli_fetch
mysqli_param_count
mysqli_send_long_data
Unfortunately, that puts a lot of updates on my queue of things to do. I imagine it likewise imposes limits on those running commercially on PHP 5.3 or older that plan an upgrade.
It does remind me that I need to pay close attention to the deprecation of mysqli
functions with each release. These are actually the largest change since PHP 5.0.