MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘MySQL’ Category

ORDER BY CASE

with 6 comments

Sometimes I give parts of a solution to increase the play time to solve a problem. I didn’t anticipate a problem when showing how to perform a sort operation with a CASE statement. It’s a sweet solution when you need to sort something differently than a traditional ascending or descending sort.

I gave my students this ORDER BY clause as an example:

  CASE
    WHEN filter = 'Debit' THEN 1
    WHEN filter = 'Credit' THEN 2
    WHEN filter = 'Total' THEN 3
  END;

It raises the following error in MySQL for students:

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 'ORDER BY
  CASE
    WHEN filter = 'Debit' THEN 1
    WHEN filter = 'Credit' THEN' at line 6

It raises the following error in Oracle for some students:

  CASE
  *
ERROR AT line 7:
ORA-01785: ORDER BY item must be the NUMBER OF a SELECT-list expression

So, I built a little test case to replicate the problem and error message they encountered:

SQL> SELECT 'Debit' AS filter FROM dual
  2  UNION ALL
  3  SELECT 'Credit' AS filter FROM dual
  4  UNION ALL
  5  SELECT 'Total' AS filter FROM dual
  6  ORDER BY
  7    CASE
  8      WHEN filter = 'Debit' THEN 1
  9      WHEN filter = 'Credit' THEN 2
 10      WHEN filter = 'Total' THEN 3
 11    END;

They said, great but how can you fix it? That’s simple, with a Common Table Expression (CTE) in Oracle or with an inline view in MySQL. The Oracle CTE solution is:

  1  WITH results AS
  2  (SELECT 'Debit' AS filter FROM dual
  3   UNION ALL
  4   SELECT 'Credit' AS filter FROM dual
  5   UNION ALL
  6   SELECT 'Total' AS filter FROM dual)
  7  SELECT filter
  8  FROM   results
  9  ORDER BY
 10    CASE
 11	 WHEN filter = 'Debit'  THEN 1
 12	 WHEN filter = 'Credit' THEN 2
 13	 WHEN filter = 'Total'  THEN 3
 14    END;

There are two MySQL solutions. One simply removes the FROM dual clauses from the query components and the other uses an inline view in the FROM clause. This is the inline view:

SELECT filter
FROM  (SELECT 'Debit' AS filter FROM dual
       UNION ALL
       SELECT 'Credit' AS filter FROM dual
       UNION ALL
       SELECT 'Total' AS filter FROM dual) resultset
ORDER BY
  CASE
    WHEN filter = 'Debit' THEN 1
    WHEN filter = 'Credit' THEN 2
    WHEN filter = 'Total' THEN 3
  END;

This is the solution without the FROM dual clauses:

SELECT 'Debit' AS filter
UNION ALL
SELECT 'Credit' AS filter
UNION ALL
SELECT 'Total' AS filter
ORDER BY
  CASE
    WHEN filter = 'Debit' THEN 1
    WHEN filter = 'Credit' THEN 2
    WHEN filter = 'Total' THEN 3
  END;

Both MySQL solutions yield the following:

+--------+
| filter |
+--------+
| Debit  |
| Credit |
| Total  |
+--------+
3 rows in set (0.00 sec)

It puts the fabricating query inside a result set, and then lets you use the column alias to filter the set. If you have a better approach, please share it.

Written by maclochlainn

July 8th, 2015 at 10:06 pm

Bash Arrays & MySQL

without comments

Student questions are always interesting! They get me to think and to write. The question this time is: “How do I write a Bash Shell script to process multiple MySQL script files?” This post builds the following model (courtesy of MySQL Workbench) by using a bash shell script and MySQL script files, but there’s a disclaimer on this post. It shows both insecure and secure approaches and you should avoid the insecure ones.

LittleERDModel

It seems a quick refresher on how to use arrays in bash shell may be helpful. While it’s essential in a Linux environment, it’s seems not everyone masters the bash shell.

Especially, since I checked my Learning the Bash Shell (2nd Edition) and found a typo on how you handle arrays in the bash shell, and it’s a mistake that could hang newbies up (on page 161). Perhaps I should update my copy because I bought it in 1998. 😉 It was good then, and the new edition is probably better. The error is probably corrected in the current Learning the Bash Shell, but if not, the following examples show you how to use arrays in loops.

Naturally, these do presume some knowledge of working with bash shell, like the first line always is the same in any bash shell script. That you open an if-statement with an if and close it with a fi, and that you else-if is elif; and that a semicolon between a for-statement and the do statement is required when they’re on the same line because they’re two statements.

If you’re new to bash shell arrays, click on the link below to expand a brief tutorial. It takes you through three progressive examples of working with bash arrays.

Only one more trick needs to be qualified before our main MySQL examples. That trick is how you pass parameters to a bash shell script. For reference, this is the part that’s insecure because user command histories are available inside the Linux OS.

Here’s a hello_whom.sh script to demonstrates the concept of parameter passing:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/bash
 
# This says hello to the argument while managing no argument.
if [[ ${#} = 1 ]]; then
  echo 'The '${0}' program says: "Hello '${1}'!"'
elif [[ ${#} > 1 ]]; then
  echo 'The '${0}' program wants to know if you have more than one name?'
else
  echo 'The '${0}' program wants to know if you have a name?'
fi

If you need more on how parameters are passed and managed, you can check a prior blob post on Handling bash Parameters, or check the bash help pages. The following leverages bash arrays to run scripts and query the MySQL database from the command line.

You will need the three batch SQL files first, so here they are:

The following list_mysql.sh shell script expects to receive the username, password, database and fully qualified path in that specific order. The script names are entered manually because this should be a unit test script. Naturally, you can extend the script to manage those parameters but as mentioned I see this type of solution as a developer machine only script to simplify unit testing. Anything beyond that is risky!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/bash
 
# Assign user and password
username="${1}"
password="${2}"
database="${3}"
directory="${4}"
 
# List the parameter values passed.
echo "Username:  " ${username}
echo "Password:  " ${password}
echo "Database:  " ${database}
echo "Directory: " ${directory}
echo ""
 
# Define an array.
declare -a cmd
 
# Assign elements to an array.
cmd[0]="actor.sql"
cmd[1]="film.sql"
cmd[2]="movie.sql"
 
# Call the array elements.
for i in ${cmd[*]}; do
  mysql -s -u${username} -p${password} -D${database} < ${directory}/${i} > /dev/null 2>/dev/null
done
 
# Connect and pipe the query result minus errors and warnings to the while loop.
mysql -u${username} -p${password} -D${database} <<<'show tables' 2>/dev/null |
 
# Read through the piped result until it's empty but format the title.
while IFS='\n' read list; do
  if [[ ${list} = "Tables_in_sampledb" ]]; then
    echo $list
    echo "----------------------------------------"
  else
    echo $list
  fi
done
echo ""
 
# Connect and pipe the query result minus errors and warnings to the while loop.
mysql -u${username} -p${password} -D${database} <<<'SELECT CONCAT(a.actor_name," in ",f.film_name) AS "Actors in Films" FROM actor a INNER JOIN movie m ON a.actor_id = m.actor_id INNER JOIN film f ON m.film_id = f.film_id' 2>/dev/null |
 
# Read through the piped result until it's empty but format the title.
while IFS='\n' read actor_name; do
  if [[ ${actor_name} = "Actors in Films" ]]; then
    echo $actor_name
    echo "----------------------------------------"
  else
    echo $actor_name
  fi
done

The IFS (Internal Field Separator) works with whitespace by default. The IFS on lines 33 and 47 sets the IFS to a line return ('\n'). That’s the trick to display the data, and you can read more about the IFS in this question and answer post.

You can run this script with the following input parameters from the local directory where you deploy it. The a parameters are: (1) username, (2) password, (3) database, and (4) a fully qualified path to the SQL setup files.

./list_mysql.sh student student sampledb "/home/student/Code/bash/mysql"

With valid input values, the list_mysql.sh bash script generates the following output, which confirms inputs and verifies actions taken by the scripts with queries:

Username:   student
Password:   student
Database:   sampledb
Directory:  /home/student/Code/bash/mysql
 
Tables_in_sampledb
----------------------------------------
actor
film
movie
 
Actors in Films
----------------------------------------
Chris Hemsworth in Thor
Chris Hemsworth in Thor: The Dark World
Chris Pine in Star Trek
Chris Pine in Star Trek into Darkness
Chris Pine in Guardians of the Galaxy

If you forgot to provide the required inputs to the list_mysql.sh bash script, it alternatively returns the following output:

Username:  
Password:  
Database:  
Directory: 
 
./list_mysql.sh: line 25: /actor.sql: No such file or directory
./list_mysql.sh: line 25: /film.sql: No such file or directory
./list_mysql.sh: line 25: /movie.sql: No such file or directory

The secure way removes the password at a minimum! The refactored program will require you to manually enter the password for all elements of the array (three in this sample), and twice for the two queries. Here’s the refactored code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/bash
 
# Assign user and password
username="${1}"
database="${2}"
directory="${3}"
 
# List the parameter values passed.
echo "Username:  " ${username}
echo "Database:  " ${database}
echo "Directory: " ${directory}
echo ""
 
# Define an array.
declare -a cmd
 
# Assign elements to an array.
cmd[0]="actor.sql"
cmd[1]="film.sql"
cmd[2]="movie.sql"
 
# Call the array elements.
for i in ${cmd[*]}; do
  mysql -s -u${username} -p -D${database} < ${directory}/${i} > /dev/null 2>/dev/null
done
 
# Connect and pipe the query result minus errors and warnings to the while loop.
mysql -u${username} -p -D${database} <<<'show tables' 2>/dev/null |
 
# Read through the piped result until it's empty.
while IFS='\n' read list; do
  if [[ ${list} = "Tables_in_sampledb" ]]; then
    echo $list
    echo "----------------------------------------"
  else
    echo $list
  fi
done
echo ""
 
# Connect and pipe the query result minus errors and warnings to the while loop.
mysql -u${username} -p -D${database} <<<'SELECT CONCAT(a.actor_name," in ",f.film_name) AS "Actors in Films" FROM actor a INNER JOIN movie m ON a.actor_id = m.actor_id INNER JOIN film f ON m.film_id = f.film_id' 2>/dev/null |
 
# Read through the piped result until it's empty.
while IFS='\n' read actor_name; do
  if [[ ${actor_name} = "Actors in Films" ]]; then
    echo $actor_name
    echo "----------------------------------------"
  else
    echo $actor_name
  fi
done

Please let me know if you think there should be any more scaffolding for newbies in this post. As always, I hope this helps those looking for this type of solution.

Written by maclochlainn

May 17th, 2015 at 12:01 pm

Eclipse, Java, MySQL

without comments

While I previously blogged about installing Netbeans 8, some of my students would prefer to use the Eclipse IDE. This post shows how to install and configure Eclipse IDE, include the mysql-connector-java.jar, and write Java to access the MySQL.

You can download Eclipse IDE and then open it in Fedora’s Archive Manager. You can use the Archive Manager to Extract the Eclipse IDE to a directory of your choice. I opted to extract it into my student user’s home directory, which is /home/student.

After extracting the Eclipse IDE, you can check the contents of the eclipse directory with the following command:

ls -al eclipse

You should see the following:

drwxrwxr-x.  8 student student   4096 May  8 22:16 .
drwx------. 33 student student   4096 May  8 21:57 ..
-rw-rw-r--.  1 student student 119194 Mar 20 07:10 artifacts.xml
drwxrwxr-x. 11 student student   4096 May  8 22:16 configuration
drwxrwxr-x.  2 student student   4096 Mar 20 07:10 dropins
-rwxr-xr-x.  1 student student  78782 Mar 20 07:08 eclipse
-rw-rw-r--.  1 student student    315 Mar 20 07:10 eclipse.ini
-rw-rw-r--.  1 student student     60 Mar 17 15:11 .eclipseproduct
drwxrwxr-x. 41 student student   4096 Mar 20 07:10 features
-rwxr-xr-x.  1 student student 140566 Mar 20 07:08 icon.xpm
drwxrwxr-x.  4 student student   4096 Mar 20 07:09 p2
drwxrwxr-x. 12 student student  40960 Mar 20 07:10 plugins
drwxrwxr-x.  2 student student   4096 Mar 20 07:10 readme

You can launch the Eclipse IDE with the following command-line from the eclipse directory:

./eclipse &

While you can run this from the /home/student/eclipse directory, it’s best to create an alias for the Eclipse IDE in the student user’s .bashrc file:

# Set alias for Eclipse IDE tool.
alias eclipse="/home/student/eclipse/eclipse"

The next time you start the student user account, you can launch the Eclipse IDE by entering eclipse in the search box opened by clicking on the Activities menu.

The following steps take you through installing Eclipse on Fedora Linux, which is more or less the same as any Linux distribution. It’s very similar on Windows platforms too.

Eclipse Installation

EclipseInstall_01

  1. Navigate to eclipse.org/downloads web page to download the current version of the Eclipse software. Click the Linux 32 Bit or Linux 64 Bit link, as required for your operating system.

  1. Click the Green Arrow to download the Eclipse software.

  1. The next dialog gives you an option to open or save the software. Click the Open with radio button to open the archive file.

  1. This the Linux Archive Manager. Click the Extract button from the menu tab to open the archive file.

  1. This extract button on file chooser dialog to install Eclipse into the /home/student/eclipse directory. Click the Extract button to let the Archive Manager create a copy of those files.

  1. The Archive Manager presents a completion dialog. Click the Close button to close the Archive Manager.

After installing the Eclipse software, you can configure Eclipse. There are sixteen steps to setup the Eclipse product. You can launch the product with the

Eclipse Setup

You need to launch the Eclipse application to perform the following steps. The syntax is the following when you did create the alias mentioned earlier in the blog post:

eclipse &

The following steps cover setting up your workspace, project, and adding the MySQL JDBC Java archive.

  1. The branding dialog may display for 30 or more seconds before the Eclipse software application launches.

  1. The Workspace Launcher opens first on a new installation. You need to designate a starting folder. I’m using /home/student/workspace as my Workspace. Click the OK button when you enter a confirmed workspace.

  1. After setting the Workspace Launcher, you open to the Eclipse Welcome page. Click second of the two icons on the left to open a working Eclipse environment. Alternatively, you can connect to Tutorials on the same page.

  1. From the developer view, click on the File menu option, the New option on the list, and the Java Project option on the floating menu. Eclipse will now create a new Java project.

  1. The New Java Project dialog lets you enter a project name and it also gives you the ability to set some basic configuration details. As a rule, you simply enter the Project Name and accept the defaults before clicking the Finish button.

  1. After creating the new Java project, Eclipse returns you to the Welcome page. Click second of the two icons on the left to open a working Eclipse environment.

  1. Now you should see the working environment. Sometimes it takes the full screen but initially it doesn’t. Navigate to the lower right hand side, and expand the window to full size.

  1. Now you should see the full screen view of the Eclipse working environment.

  1. Now you create a new Java class by navigating to the File menu options, then the New menu option, and finally choosing the Class floating menu.

  1. The New Java Class dialog requires you to provide some information about the Java object you’re creating. The most important thing is the Java class name.

  1. The only difference in this copy of the New Java Class dialog is that I’ve entered HelloWorld as the Java Class’s name. Click the Finish button when you’re done.

  1. Eclipse should show you the following HelloWorld.java file. It’s missing a main() method. Add a static main() method to the HelloWorld.java class source file.

  1. This form shows the changes to the HelloWorld.java file. Specifically, it adds the It’s missing a main() method. Add a static main() method to the HelloWorld.java class source file.

  1. You can click the green arrow from the tool panel or you can click the Run menu option and Run submenu choice to test your program.

    1
    2
    3
    4
    
    // Class definition.
    public class HelloWorld {
      public static void main(String args[]) {
        System.out.println("Hello World."); }}

  1. The Save and Launch dialog tells you that you’re ready to test creating a copy of the Java class file. Click the OK button to continue.

  1. The results from your program are written to the Console portion of the Eclipse IDE. This concludes the setup of a workspace, project, and deployment of actual Java classes.

    Hello World.

Add MySQL JDBC Library

The following instructions add the MySQL Library and demonstrate how to write Java programs that connect to the MySQL database. They also use the mysql project.

EclipseMySQLLib_01

  1. Navigate to the Project menu and choose the Properties menu option.

EclipseMySQLLib_02

  1. The Properties menu option opens the Properties for the mysql project on the Order and Export tab. Click the Libraries tab to add an external library.

EclipseMySQLLib_03

  1. In the Libraries tab click the Add Library… button on the right to add an external library.

EclipseMySQLLib_04

  1. In the JAR Selection dialog, click on Computer in the Places list, then click on usr, click on share, and click on java. The Name list should now include mysql-connector-java.jar file, and you should click on it before clicking on the OK button.

EclipseMySQLLib_05

  1. You create new Java class file by clicking on the File menu. Then, you choose the New menu option and the Class menu option from the floating menu.

EclipseMySQLLib_06

  1. Enter MysqlConnector as the name of the new Java class file and click the Finish button to continue.

EclipseMySQLLib_07

  1. Eclipse generates the shell of the MysqlConnector class as shown in the illustration to the left.

EclipseMySQLLib_08

  1. You should replace the MysqlConnector class shell with the code below. Then, click the green arrow or the Run menu and Run menu option to compile and run the new MysqlConnector Java class file.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
     
    public class MysqlConnector extends Object {
      public static void main(String[] args) {
        try {
          /* The newInstance() call is a work around for some
             broken Java implementations. */
          Class.forName("com.mysql.jdbc.Driver").newInstance();
     
          /* Verify the Java class path. */
          System.out.println("====================");
          System.out.println("CLASSPATH [" + System.getProperty("java.class.path") + "]");
          System.out.println("====================");
     
        } catch (Exception e) {}
        finally {
          /* Verify the Java class path. */
          System.out.println("====================");
          System.out.println("CLASSPATH [" + System.getProperty("java.class.path") + "]");
          System.out.println("====================");
        }
      }
    }

EclipseMySQLLib_09

  1. The Save and Launch dialog informs you are saving a MysqlConnector.java file to your mysql project. Click the OK button to continue.

EclipseMySQLLib_10

  1. The next screen shows that the program successfully connected to the MySQL database by printing the following information to the Console output tab.

    ====================
    CLASSPATH [/home/student/Code/workspace/MySQL/bin:/usr/share/java/mysql-connector-java.jar]
    ====================
    ====================
    CLASSPATH [/home/student/Code/workspace/MySQL/bin:/usr/share/java/mysql-connector-java.jar]
    ====================

EclipseMySQLLib_11

  1. Instead of repeating steps #5 through #10, the image displays the testing of the MysqlResults class file. The code follows below:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    
    /* Import the java.sql.* package. */
    import java.sql.*;
     
    /* You can't include the following on Linux without raising an exception. */
    // import com.mysql.jdbc.Driver;
     
    public class MySQLResult {
      public MySQLResult() {
        /* Declare variables that require explicit assignments because
           they're addressed in the finally block. */
        Connection conn = null;
        Statement stmt = null;
        ResultSet rset = null;
     
        /* Declare other variables. */
        String url;
        String username = "student";
        String password = "student";
        String database = "studentdb";
        String hostname = "localhost";
        String port = "3306";
        String sql;
     
        /* Attempt a connection. */
        try {
          // Set URL.
          url = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
     
          // Create instance of MySQL.
          Class.forName ("com.mysql.jdbc.Driver").newInstance();
          conn = DriverManager.getConnection (url, username, password);
     
          // Query the version of the database, relies on *_ri2.sql scripts.
          sql = "SELECT i.item_title, ra.rating FROM item i INNER JOIN rating_agency ra ON i.item_rating_id = ra.rating_agency_id";
          stmt = conn.createStatement();
          rset = stmt.executeQuery(sql);
     
          System.out.println ("Database connection established");
     
          // Read row returns for one column.
          while (rset.next()) {
            System.out.println(rset.getString(1) + ", " + rset.getString(2)); }
     
        }
        catch (SQLException e) {
          System.err.println ("Cannot connect to database server (SQLException):");
          System.out.println(e.getMessage());
        }
        catch (ClassNotFoundException e) {
          System.err.println ("Cannot connect to database server (ClassNotFoundException)");
          System.out.println(e.getMessage());
        }
        catch (InstantiationException e) {
          System.err.println ("Cannot connect to database server (InstantiationException)");
          System.out.println(e.getMessage());
        }
        catch (IllegalAccessException e) {
          System.err.println ("Cannot connect to database server (IllegalAccesException)");
          System.out.println(e.getMessage());
        }
        finally {
          if (conn != null) {
            try {
              rset.close();
              stmt.close();
              conn.close();
              System.out.println ("Database connection terminated");
            }
            catch (Exception e) { /* ignore close errors */ }
          }
        }
      }
      /* Unit test. */
      public static void main(String args[]) {
        new MySQLResult(); }
    }

    After you click the green arrow or the Run menu and Run menu option to compile and run the program, you should see the following output. That is if you’re using my create_mysql_store_ri2.sql and seed_mysql_store_ri2.sql files.

    Database connection established
    I Remember Mama, NR
    Tora! Tora! Tora!, G
    A Man for All Seasons, G
    Around the World in 80 Days, G
    Camelot, G
    Christmas Carol, G
    I Remember Mama, G
    The Hunt for Red October, PG
    Star Wars I, PG
    Star Wars II, PG
    Star Wars II, PG
    The Chronicles of Narnia, PG
    Beau Geste, PG
    Hook, PG
    Harry Potter and the Sorcerer's Stone, PG
    Scrooge, PG
    Harry Potter and the Sorcer's Stone, PG
    Harry Potter and the Sorcer's Stone, PG
    Harry Potter and the Chamber of Secrets, PG
    Harry Potter and the Chamber of Secrets, PG
    Harry Potter and the Prisoner of Azkaban, PG
    Harry Potter and the Prisoner of Azkaban, PG
    Harry Potter and the Half Blood Prince, PG
    Star Wars III, PG-13
    Casino Royale, PG-13
    Casino Royale, PG-13
    Die Another Day, PG-13
    Die Another Day, PG-13
    Die Another Day, PG-13
    Golden Eye, PG-13
    Golden Eye, PG-13
    Tomorrow Never Dies, PG-13
    Tomorrow Never Dies, PG-13
    The World Is Not Enough, PG-13
    Clear and Present Danger, PG-13
    Clear and Present Danger, PG-13
    Harry Potter and the Goblet of Fire, PG-13
    Harry Potter and the Goblet of Fire, PG-13
    Harry Potter and the Goblet of Fire, PG-13
    Harry Potter and the Order of the Phoenix, PG-13
    Harry Potter and the Deathly Hallows, Part 1, PG-13
    Harry Potter and the Deathly Hallows, Part 2, PG-13
    Brave Heart, R
    The Chronicles of Narnia, E
    MarioKart, E
    Need for Speed, E
    Cars, E
    RoboCop, M
    Pirates of the Caribbean, T
    Splinter Cell, T
    The DaVinci Code, T
    Database connection terminated

As always, I hope the note helps those trying to work with the Eclipse product.

Written by maclochlainn

May 10th, 2015 at 2:09 am

MySQL OCP Exams

with 6 comments

Planning out my year, I decided to take the Oracle OCP and MySQL OCP exams. I checked for review books and was pleasantly surprised to find the soon to be released OCP MySQL Database Administrator Exam Guide (Exam 1Z0-883). However, I noticed that the book was actually prepared for the obsolete and discountinued Exams 1Z0-870, 1Z0-873, and 1Z0-874. As it turns out, Steve O’Hearn has informed me that there isn’t a book and that the posting in Amazon.com is in error.

There isn’t an alternative review book for the OCP MySQL 5.6 Developer or Database Administrator Exams. The question that I have is simple: “How relevant is this book because it was prepared for the older exams?” There isn’t a table of content published on the Amazon.com site. If there was a table of contents it could help me determine how close the book’s content is to the new exam.

As a preparation to figure out the value of the book as a study guide, I’ve reviewed the current Oracle MySQL Training Objectives (listed below). The new MySQL OCP Developer and Administrator exams have the following descriptions and objectives:

  • MySQL 5.6 Developer 1Z0-882. Oracle provides the following outline for their MySQL for Developer (Ed 3) training course:

    Course Objectives

    • Describe the MySQL client/server architecture
    • Use MySQL client programs and common options
    • Program MySQL applications with Java and PHP connectors
    • Use a “NoSQL” approach to store and retrieve data
    • Design efficient tables
    • Create and delete database objects
    • Use expressions in SQL statements
    • Examine database metadata
    • Use SQL statements to modify table data
    • Maintain database integrity with transactions
    • Write multiple table queries
    • Create “virtual tables” containing specific data
    • Create user-defined variables, prepared statements, and stored routines
    • Create and manage triggers
    • Identify and deal with errors and exceptions in client programs
    • Write queries that are fast and effective, even under heavy loads
  • MySQL 5.6 Database Administrator 1Z0-883. Oracle provides the following outline for their MySQL for Database Administrators (Ed 3.1) training course:

    Course Objectives

    • Describe the MySQL Architecture
    • Install and Upgrade MySQL
    • Use the INFORMATION_SCHEMA database to access metadata
    • Perform the MySQL start and shutdown operations
    • Configure MySQL server options at runtime
    • Use available tools including MySQL Workbench
    • Evaluate data types and character sets for performance issues
    • Understand data locking in MySQL
    • Understand the use of the InnoDB storage engine with MySQL
    • Maintain integrity of a MySQL installation
    • Use triggers for administration tasks
    • Use Enterprise Audit and Pluggable Authentication
    • Configure advanced replication topologies for high availability
    • Describe introductory performance tuning techniques
    • Perform backup and restore operations
    • Automate administrative tasks with scheduled events

    As always, I hope this helps those who read it; and, in this case I hope it helps you make an effective decision on preparation resources for the MySQL 5.6 OCP exams.

Written by maclochlainn

April 24th, 2015 at 12:39 am

Ruby-MySQL Columns

with one comment

Last week I posted how to configure and test Ruby and MySQL. Somebody asked me how to handle a dynamic list of columns. So, here’s a quick little program to show you how to read the dynamic list of column:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
require 'rubygems'
require 'mysql'
 
# Begin block.
begin
  # Create a new connection resource.
  db = Mysql.new('localhost','student','student','studentdb')
 
  # Create a result set.
  rs = db.query('SELECT item_title, item_rating FROM item')
  # Read through the result set hash.
  rs.each do | row |
    out = ""
    i = 0
    while i < db.field_count
      # Check if not last column.
      if i < db.field_count - 1
        out += "#{row[i]}, "
      else
        out += "#{row[i]}"
      end
      i += 1
    end
    puts "#{out}"
  end
  # Release the result set resources.
  rs.free
rescue Mysql::Error => e
  # Print the error.
  puts "ERROR #{e.errno} (#{e.sqlstate}): #{e.error}"
  puts "Can't connect to MySQL database specified."
  # Signal an error.
  exit 1
ensure
  # Close the connection when it is open.
  db.close if db
end

The new logic on lines 13 through 22 reads the list of columns into a comma delimited list of values. The if-block checks to make sure it doesn’t append a comma to the last column in the list. It prints output like:

The Hunt for Red October, PG
Star Wars I, PG
Star Wars II, PG
Star Wars II, PG
Star Wars III, PG13
The Chronicles of Narnia, PG
RoboCop, Mature
Pirates of the Caribbean, Teen
The Chronicles of Narnia, Everyone
MarioKart, Everyone
Splinter Cell, Teen
Need for Speed, Everyone
The DaVinci Code, Teen
Cars, Everyone
Beau Geste, PG
I Remember Mama, NR
Tora! Tora! Tora!, G
A Man for All Seasons, G
Hook, PG
Around the World in 80 Days, G
Harry Potter and the Sorcerer's Stone, PG
Camelot, G

As always, I hope this helps those looking for a solution.

Written by maclochlainn

April 18th, 2015 at 2:25 am

Java-MySQL Program

with one comment

It turns out that configuring Perl wasn’t the last step for my student instance. It appears that I neglected to configure my student instance to support Java connectivity to MySQL. This post reviews the configuration of Java to run programs against MySQL. It also covers the new syntax on how you register a DriverManager, and avoid Java compilation errors with the older syntax.

In prior posts, I’ve shown how to use Perl , PHP, Python, and Ruby languages to query a MySQL database on Linux.

You need to install the Open JDK libraries with the yum utility command:

yum install -y java-1.7.0-openjdk*

It should generate the following log output:

Loaded plugins: langpacks, refresh-packagekit
Package 1:java-1.7.0-openjdk-1.7.0.75-2.5.4.2.fc20.x86_64 already installed and latest version
Package 1:java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.fc20.x86_64 already installed and latest version
Resolving Dependencies
--> Running transaction check
---> Package java-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed
--> Processing Dependency: java-atk-wrapper for package: 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20.x86_64
---> Package java-1.7.0-openjdk-demo.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed
---> Package java-1.7.0-openjdk-devel.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed
---> Package java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.75-2.5.4.2.fc20 will be installed
---> Package java-1.7.0-openjdk-src.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed
--> Running transaction check
---> Package java-atk-wrapper.x86_64 0:0.30.4-4.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                          Arch   Version                  Repository
                                                                           Size
================================================================================
Installing:
 java-1.7.0-openjdk-accessibility x86_64 1:1.7.0.75-2.5.4.2.fc20  updates  32 k
 java-1.7.0-openjdk-demo          x86_64 1:1.7.0.75-2.5.4.2.fc20  updates 1.9 M
 java-1.7.0-openjdk-devel         x86_64 1:1.7.0.75-2.5.4.2.fc20  updates 9.2 M
 java-1.7.0-openjdk-javadoc       noarch 1:1.7.0.75-2.5.4.2.fc20  updates  14 M
 java-1.7.0-openjdk-src           x86_64 1:1.7.0.75-2.5.4.2.fc20  updates  39 M
Installing for dependencies:
 java-atk-wrapper                 x86_64 0.30.4-4.fc20            fedora   71 k
 
Transaction Summary
================================================================================
Install  12 Packages (+1 Dependent package)
 
Total download size: 163 M
Installed size: 765 M
Downloading packages:
(1/6): java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.f |  32 kB  00:00     
(2/6): java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_6 | 1.9 MB  00:02     
(3/6): java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_ | 9.2 MB  00:05     
(4/6): java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.no |  14 MB  00:04     
(5/6): java-atk-wrapper-0.30.4-4.fc20.x86_64.rpm           |  71 kB  00:00     
(6/6): java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_6  |  39 MB  00:23     
--------------------------------------------------------------------------------
Total                                             4.5 MB/s | 163 MB  00:36     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : java-atk-wrapper-0.30.4-4.fc20.x86_64                       3/13 
  Installing : 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20    4/13 
  Installing : 1:java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_64     9/13 
  Installing : 1:java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_64      10/13 
  Installing : 1:java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.noarc   12/13 
  Installing : 1:java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_64     13/13 
  Verifying  : 1:java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_64      2/13 
  Verifying  : 1:java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.noarc    3/13 
  Verifying  : java-atk-wrapper-0.30.4-4.fc20.x86_64                       5/13 
  Verifying  : 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20    6/13 
  Verifying  : 1:java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_64     8/13 
  Verifying  : 1:java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_64      12/13 
 
Installed:
  java-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.75-2.5.4.2.fc20               
  java-1.7.0-openjdk-demo.x86_64 1:1.7.0.75-2.5.4.2.fc20                        
  java-1.7.0-openjdk-devel.x86_64 1:1.7.0.75-2.5.4.2.fc20                       
  java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.75-2.5.4.2.fc20                     
  java-1.7.0-openjdk-src.x86_64 1:1.7.0.75-2.5.4.2.fc20                         
 
Dependency Installed:
  java-atk-wrapper.x86_64 0:0.30.4-4.fc20                                       
 
Complete!

You can find the Java compiler’s version with the following command:

javac -version

It should show you the following Java version:

javac 1.7.0_75

Next, you need to install the mysql-connector-java library with yum like this:

yum install -y mysql-connector-java

It should generate the following installation output:

Loaded plugins: langpacks, refresh-packagekit
mysql-connectors-community                                  | 2.5 kB  00:00     
mysql-tools-community                                       | 2.5 kB  00:00     
mysql56-community                                           | 2.5 kB  00:00     
pgdg93                                                      | 3.6 kB  00:00     
updates/20/x86_64/metalink                                  |  15 kB  00:00     
Resolving Dependencies
--> Running transaction check
---> Package mysql-connector-java.noarch 1:5.1.28-1.fc20 will be installed
--> Processing Dependency: jta >= 1.0 for package: 1:mysql-connector-java-5.1.28-1.fc20.noarch
--> Processing Dependency: slf4j for package: 1:mysql-connector-java-5.1.28-1.fc20.noarch
--> Running transaction check
---> Package geronimo-jta.noarch 0:1.1.1-15.fc20 will be installed
---> Package slf4j.noarch 0:1.7.5-3.fc20 will be installed
--> Processing Dependency: mvn(log4j:log4j) for package: slf4j-1.7.5-3.fc20.noarch
--> Processing Dependency: mvn(javassist:javassist) for package: slf4j-1.7.5-3.fc20.noarch
--> Processing Dependency: mvn(commons-logging:commons-logging) for package: slf4j-1.7.5-3.fc20.noarch
--> Processing Dependency: mvn(commons-lang:commons-lang) for package: slf4j-1.7.5-3.fc20.noarch
--> Processing Dependency: mvn(ch.qos.cal10n:cal10n-api) for package: slf4j-1.7.5-3.fc20.noarch
--> Running transaction check
---> Package apache-commons-lang.noarch 0:2.6-13.fc20 will be installed
---> Package apache-commons-logging.noarch 0:1.1.3-8.fc20 will be installed
--> Processing Dependency: mvn(logkit:logkit) for package: apache-commons-logging-1.1.3-8.fc20.noarch
--> Processing Dependency: mvn(avalon-framework:avalon-framework-api) for package: apache-commons-logging-1.1.3-8.fc20.noarch
---> Package cal10n.noarch 0:0.7.7-3.fc20 will be installed
---> Package javassist.noarch 0:3.16.1-6.fc20 will be installed
---> Package log4j.noarch 0:1.2.17-14.fc20 will be installed
--> Processing Dependency: mvn(org.apache.geronimo.specs:geronimo-jms_1.1_spec) for package: log4j-1.2.17-14.fc20.noarch
--> Processing Dependency: mvn(javax.mail:mail) for package: log4j-1.2.17-14.fc20.noarch
--> Running transaction check
---> Package avalon-framework.noarch 0:4.3-9.fc20 will be installed
--> Processing Dependency: xalan-j2 for package: avalon-framework-4.3-9.fc20.noarch
---> Package avalon-logkit.noarch 0:2.1-13.fc20 will be installed
--> Processing Dependency: tomcat-servlet-3.0-api for package: avalon-logkit-2.1-13.fc20.noarch
---> Package geronimo-jms.noarch 0:1.1.1-17.fc20 will be installed
---> Package javamail.noarch 0:1.5.0-6.fc20 will be installed
--> Running transaction check
---> Package tomcat-servlet-3.0-api.noarch 0:7.0.52-2.fc20 will be installed
---> Package xalan-j2.noarch 0:2.7.1-22.fc20 will be installed
--> Processing Dependency: xerces-j2 for package: xalan-j2-2.7.1-22.fc20.noarch
--> Processing Dependency: osgi(org.apache.xerces) for package: xalan-j2-2.7.1-22.fc20.noarch
--> Running transaction check
---> Package xerces-j2.noarch 0:2.11.0-17.fc20 will be installed
--> Processing Dependency: xml-commons-resolver >= 1.2 for package: xerces-j2-2.11.0-17.fc20.noarch
--> Processing Dependency: xml-commons-apis >= 1.4.01 for package: xerces-j2-2.11.0-17.fc20.noarch
--> Processing Dependency: osgi(org.apache.xml.resolver) for package: xerces-j2-2.11.0-17.fc20.noarch
--> Processing Dependency: osgi(javax.xml) for package: xerces-j2-2.11.0-17.fc20.noarch
--> Running transaction check
---> Package xml-commons-apis.noarch 0:1.4.01-14.fc20 will be installed
---> Package xml-commons-resolver.noarch 0:1.2-14.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                    Arch       Version                Repository   Size
================================================================================
Installing:
 mysql-connector-java       noarch     1:5.1.28-1.fc20        updates     1.3 M
Installing for dependencies:
 apache-commons-lang        noarch     2.6-13.fc20            fedora      281 k
 apache-commons-logging     noarch     1.1.3-8.fc20           updates      78 k
 avalon-framework           noarch     4.3-9.fc20             fedora       87 k
 avalon-logkit              noarch     2.1-13.fc20            fedora       87 k
 cal10n                     noarch     0.7.7-3.fc20           fedora       37 k
 geronimo-jms               noarch     1.1.1-17.fc20          fedora       32 k
 geronimo-jta               noarch     1.1.1-15.fc20          fedora       21 k
 javamail                   noarch     1.5.0-6.fc20           fedora      606 k
 javassist                  noarch     3.16.1-6.fc20          fedora      626 k
 log4j                      noarch     1.2.17-14.fc20         fedora      449 k
 slf4j                      noarch     1.7.5-3.fc20           fedora      173 k
 tomcat-servlet-3.0-api     noarch     7.0.52-2.fc20          updates     207 k
 xalan-j2                   noarch     2.7.1-22.fc20          updates     1.9 M
 xerces-j2                  noarch     2.11.0-17.fc20         updates     1.1 M
 xml-commons-apis           noarch     1.4.01-14.fc20         fedora      227 k
 xml-commons-resolver       noarch     1.2-14.fc20            fedora      108 k
 
Transaction Summary
================================================================================
Install  1 Package (+16 Dependent packages)
 
Total download size: 7.3 M
Installed size: 10 M
Downloading packages:
(1/17): apache-commons-logging-1.1.3-8.fc20.noarch.rpm      |  78 kB  00:00     
(2/17): apache-commons-lang-2.6-13.fc20.noarch.rpm          | 281 kB  00:00     
(3/17): avalon-framework-4.3-9.fc20.noarch.rpm              |  87 kB  00:00     
(4/17): avalon-logkit-2.1-13.fc20.noarch.rpm                |  87 kB  00:00     
(5/17): cal10n-0.7.7-3.fc20.noarch.rpm                      |  37 kB  00:00     
(6/17): geronimo-jms-1.1.1-17.fc20.noarch.rpm               |  32 kB  00:00     
(7/17): geronimo-jta-1.1.1-15.fc20.noarch.rpm               |  21 kB  00:00     
(8/17): javamail-1.5.0-6.fc20.noarch.rpm                    | 606 kB  00:00     
(9/17): javassist-3.16.1-6.fc20.noarch.rpm                  | 626 kB  00:00     
(10/17): log4j-1.2.17-14.fc20.noarch.rpm                    | 449 kB  00:00     
(11/17): slf4j-1.7.5-3.fc20.noarch.rpm                      | 173 kB  00:00     
(12/17): mysql-connector-java-5.1.28-1.fc20.noarch.rpm      | 1.3 MB  00:01     
(13/17): tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch.rpm    | 207 kB  00:00     
(14/17): xalan-j2-2.7.1-22.fc20.noarch.rpm                  | 1.9 MB  00:00     
(15/17): xerces-j2-2.11.0-17.fc20.noarch.rpm                | 1.1 MB  00:00     
(16/17): xml-commons-apis-1.4.01-14.fc20.noarch.rpm         | 227 kB  00:00     
(17/17): xml-commons-resolver-1.2-14.fc20.noarch.rpm        | 108 kB  00:00     
--------------------------------------------------------------------------------
Total                                              1.3 MB/s | 7.3 MB  00:05     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : xml-commons-apis-1.4.01-14.fc20.noarch                      1/17 
  Installing : geronimo-jms-1.1.1-17.fc20.noarch                           2/17 
  Installing : xml-commons-resolver-1.2-14.fc20.noarch                     3/17 
  Installing : xerces-j2-2.11.0-17.fc20.noarch                             4/17 
  Installing : xalan-j2-2.7.1-22.fc20.noarch                               5/17 
  Installing : javamail-1.5.0-6.fc20.noarch                                6/17 
  Installing : log4j-1.2.17-14.fc20.noarch                                 7/17 
  Installing : tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch                 8/17 
  Installing : avalon-framework-4.3-9.fc20.noarch                          9/17 
  Installing : avalon-logkit-2.1-13.fc20.noarch                           10/17 
  Installing : apache-commons-logging-1.1.3-8.fc20.noarch                 11/17 
  Installing : javassist-3.16.1-6.fc20.noarch                             12/17 
  Installing : cal10n-0.7.7-3.fc20.noarch                                 13/17 
  Installing : apache-commons-lang-2.6-13.fc20.noarch                     14/17 
  Installing : slf4j-1.7.5-3.fc20.noarch                                  15/17 
  Installing : geronimo-jta-1.1.1-15.fc20.noarch                          16/17 
  Installing : 1:mysql-connector-java-5.1.28-1.fc20.noarch                17/17 
  Verifying  : geronimo-jta-1.1.1-15.fc20.noarch                           1/17 
  Verifying  : geronimo-jms-1.1.1-17.fc20.noarch                           2/17 
  Verifying  : xalan-j2-2.7.1-22.fc20.noarch                               3/17 
  Verifying  : apache-commons-lang-2.6-13.fc20.noarch                      4/17 
  Verifying  : slf4j-1.7.5-3.fc20.noarch                                   5/17 
  Verifying  : log4j-1.2.17-14.fc20.noarch                                 6/17 
  Verifying  : avalon-framework-4.3-9.fc20.noarch                          7/17 
  Verifying  : xerces-j2-2.11.0-17.fc20.noarch                             8/17 
  Verifying  : cal10n-0.7.7-3.fc20.noarch                                  9/17 
  Verifying  : avalon-logkit-2.1-13.fc20.noarch                           10/17 
  Verifying  : 1:mysql-connector-java-5.1.28-1.fc20.noarch                11/17 
  Verifying  : xml-commons-resolver-1.2-14.fc20.noarch                    12/17 
  Verifying  : xml-commons-apis-1.4.01-14.fc20.noarch                     13/17 
  Verifying  : javassist-3.16.1-6.fc20.noarch                             14/17 
  Verifying  : tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch                15/17 
  Verifying  : javamail-1.5.0-6.fc20.noarch                               16/17 
  Verifying  : apache-commons-logging-1.1.3-8.fc20.noarch                 17/17 
 
Installed:
  mysql-connector-java.noarch 1:5.1.28-1.fc20                                   
 
Dependency Installed:
  apache-commons-lang.noarch 0:2.6-13.fc20                                      
  apache-commons-logging.noarch 0:1.1.3-8.fc20                                  
  avalon-framework.noarch 0:4.3-9.fc20                                          
  avalon-logkit.noarch 0:2.1-13.fc20                                            
  cal10n.noarch 0:0.7.7-3.fc20                                                  
  geronimo-jms.noarch 0:1.1.1-17.fc20                                           
  geronimo-jta.noarch 0:1.1.1-15.fc20                                           
  javamail.noarch 0:1.5.0-6.fc20                                                
  javassist.noarch 0:3.16.1-6.fc20                                              
  log4j.noarch 0:1.2.17-14.fc20                                                 
  slf4j.noarch 0:1.7.5-3.fc20                                                   
  tomcat-servlet-3.0-api.noarch 0:7.0.52-2.fc20                                 
  xalan-j2.noarch 0:2.7.1-22.fc20                                               
  xerces-j2.noarch 0:2.11.0-17.fc20                                             
  xml-commons-apis.noarch 0:1.4.01-14.fc20                                      
  xml-commons-resolver.noarch 0:1.2-14.fc20                                     
 
Complete!

I must write too much Java code for the Windows platform because I didn’t notice the change in how the DriverManager should be instantiated. Initially, I wrote the program using the following declaration for the DriverManager class:

30
      DriverManager.registerDriver(new com.mysql.jdbc.Driver());

While it worked on Windows, the same syntax in the MySQL.java program raised two errors on the Linux server. One for the declaration of the com.mysql.jdbc.Driver class and another trying to declare an instance of Driver class.

These are the two errors:

MySQL.java:5: error: package com.mysql.jdbc does not exist
import com.mysql.jdbc.Driver;
                     ^
MySQL.java:31: error: package com.mysql.jdbc does not exist
      DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                                                     ^

I rewrote the MySQL.java program as follows, and it works on both implementations:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Import classes.
import java.sql.*;
 
/* You can't include the following on Linux without raising an exception. */
// import com.mysql.jdbc.Driver;
 
public class MySQL {
  public MySQL() {
    /* Declare variables that require explicit assignments because
       they're addressed in the finally block. */
    Connection conn = null;
    Statement stmt = null;
    ResultSet rset = null;
 
    /* Declare other variables. */
    String url;
    String username = "student";
    String password = "student";
    String database = "studentdb";
    String hostname = "localhost";
    String port = "3306";
    String sql;
 
    /* Attempt a connection. */
    try {
      // Set URL.
      url = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
 
      // Create instance of MySQL.
      Class.forName ("com.mysql.jdbc.Driver").newInstance();
      conn = DriverManager.getConnection (url, username, password);
 
      // Query the version of the database.
      sql = "SELECT version()";
      stmt = conn.createStatement();
      rset = stmt.executeQuery(sql);
 
      System.out.println ("Database connection established");
 
      // Read row returns for one column.
      while (rset.next()) {
        System.out.println("MySQL Version [" + rset.getString(1) + "]"); }
 
    }
    catch (SQLException e) {
      System.err.println ("Cannot connect to database server:");
      System.out.println(e.getMessage());
    }
    catch (ClassNotFoundException e) {
      System.err.println ("Cannot connect to database server:");
      System.out.println(e.getMessage());
    }
    catch (InstantiationException e) {
      System.err.println ("Cannot connect to database server:");
      System.out.println(e.getMessage());
    }
    catch (IllegalAccessException e) {
      System.err.println ("Cannot connect to database server:");
      System.out.println(e.getMessage());
    }
    finally {
      if (conn != null) {
        try {
          rset.close();
          stmt.close();
          conn.close();
          System.out.println ("Database connection terminated");
        }
        catch (Exception e) { /* ignore close errors */ }
      }
    }
  }
  /* Unit test. */
  public static void main(String args[]) {
    new MySQL();
  }
}

The old approach to the DriverManager and Driver classes disallows the use of three of the exceptions in the sample code: ClassNotFoundException, InstantiationException, and IllegalAccessException classes. The new syntax works on Linux, Mac OS X, and Windows. If you’re running on Mac OS X, you need to import the following additional library in the MySQL.java program:

import com.apple.eawt.*;

Before you compile the MySQL.java program, you need to put the mysql-connector-java.jar and your present working directory into your environment’s $CLASSPATH variable. You can set the $CLASSPATH variable at the command-line or embed the following in your .bashrc file:

export CLASSPATH=/usr/share/java/mysql-connector-java.jar:.

If you embedded it in the .bashrc file, you need to source that file or restart your terminal session, which resources the .bashrc for you. You can source your .bashrc file from an active Terminal session in your home directory with this syntax:

. ./.bashrc

If you’re new to Java and the MySQL Connector/J, you compile the MySQL.java program with the following syntax. At least, it works when you have the MySQL.java source file in the present working directory and want to create the class file in the same directory. You can find more about the javac command-line at the www.tutorialpoint.com web site>

javac -verbose -cp . MySQL.java

Then, you can run it with the class file with this syntax:

java MySQL

It should return the following:

Database connection established
MySQL Version [5.6.24]
Database connection terminated

If you’d prefer to return data, you can replace line 34 in the MySQL.java program with a query against a table, like:

34
      sql = "SELECT item_title, item_rating FROM item";

Then, change line 42 in the MySQL.java program with syntax to manage the output, like:

42
        System.out.println(rset.getString(1) + ", " + rset.getString(2)); }

Recompile it, and rerun the MySQL class file with this syntax:

java MySQL

It should return the following:

Database connection established
The Hunt for Red October, PG
Star Wars I, PG
Star Wars II, PG
Star Wars II, PG
Star Wars III, PG13
The Chronicles of Narnia, PG
RoboCop, Mature
Pirates of the Caribbean, Teen
The Chronicles of Narnia, Everyone
MarioKart, Everyone
Splinter Cell, Teen
Need for Speed, Everyone
The DaVinci Code, Teen
Cars, Everyone
Beau Geste, PG
I Remember Mama, NR
Tora! Tora! Tora!, G
A Man for All Seasons, G
Hook, PG
Around the World in 80 Days, G
Harry Potter and the Chamber of Secrets, PG
Camelot, G
Database connection terminated

As always, I hope this helps those looking for a solution.

Written by maclochlainn

April 17th, 2015 at 5:16 pm

MySQLdb Manage Columns

without comments

Sometimes trying to keep a post short and to the point raises other questions. Clearly, my Python-MySQL Program post over the weekend did raise a question. They were extending the query example and encountered this error:

TypeError: range() integer end argument expected, got tuple.

That should be a straight forward error message because of two things. First, the Python built-in range() function manages a range of numbers. Second, the row returned from a cursor is actually a tuple (from relational algebra), and it may contain non-numeric data like strings and dates.

The reader was trying to dynamically navigate the number of columns in a row by using the range() function like this (where row was a row from the cursor or result set):

    for j in range(row):

Naturally, it threw the type mismatch error noted above. As promised, the following Python program fixes that problem. It also builds on the prior example by navigatung an unknown list of columns. Lines 16 through 31 contain the verbose comments and programming logic to dynamically navigate the columns of a row.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/usr/bin/python
 
# Import sys library.
import MySQLdb
import sys
 
try:
  # Create new database connection.
  db = MySQLdb.connect('localhost','student','student','studentdb')
  # Create a result set cursor.
  rs = db.cursor()
  rs.execute("SELECT item_title, item_subtitle, item_rating FROM item")
  # Assign the query results to a local variable.
  for i in range(rs.rowcount):
    row = rs.fetchone()
    # Initialize variable for printing row as a string.
    data = ""
    # Address an indefinite number of columns.
    count = 0
    for j in range(len(row)):
      # Initialize column value as an empty string.
      datum = ""
      # Replace column values when they exist.
      if str(row[count]) != 'None':
        datum = str(row[count])
      # Append a comma when another column follows.
      if count == len(row) - 1:
        data += datum
      else:
        data += datum + ", "
      count += 1
    # Print the formatted row as a string.
    print data
except MySQLdb.Error, e:
  # Print the error.
  print "ERROR %d: %s" % (e.args[0], e.args[1])
  sys.exit(1)
finally:
  # Close the connection when it is open.
  if db:
    db.close()

There are a couple Python programming techniques that could be perceived as tricks. Line 24 checks for a not null value by explicitly casting the column’s value to a string and then comparing its value against the string equivalent for a null. The MySQLdb returns a 'None' string for null values by default. The if-block on lines 27 through 30 ensure commas aren’t appended at the end of a row.

While the for-loop with a range works, I’d recommend you write it as a while-loop because its easier to read for most new Python programmers. You only need to replace line 20 with the following to make the change:

20
    while (count < len(row)):

Either approach generates output like:

The Hunt for Red October, Special Collectornulls Edition, PG
Star Wars I, Phantom Menace, PG
Star Wars II, Attack of the Clones, PG
Star Wars II, Attack of the Clones, PG
Star Wars III, Revenge of the Sith, PG-13
The Chronicles of Narnia, The Lion, the Witch and the Wardrobe, PG
RoboCop, , Mature
Pirates of the Caribbean, , Teen
The Chronicles of Narnia, The Lion, the Witch and the Wardrobe, Everyone
MarioKart, Double Dash, Everyone
Splinter Cell, Chaos Theory, Teen
Need for Speed, Most Wanted, Everyone
The DaVinci Code, , Teen
Cars, , Everyone
Beau Geste, , PG
I Remember Mama, , NR
Tora! Tora! Tora!, The Attack on Pearl Harbor, G
A Man for All Seasons, , G
Hook, , PG
Around the World in 80 Days, , G
Harry Potter and the Sorcerer's Stone, , PG
Camelot, , G

As always, I hope this helps those looking for clarity.

Written by maclochlainn

April 13th, 2015 at 10:05 pm

Perl-MySQL Program

with 2 comments

Configuring Perl to work with MySQL is the last part creating a complete Fedora Linux LAMP stack for my students. Perl is already installed on Fedora Linux.

I’ve also shown how to use PHP, Python, and Ruby languages to query a MySQL database on Linux. After installing this additional Perl DBI library, my students will have the opportunity to choose how they implement their LAMP solution.

You can find the Perl version with the following version.pl program:

1
2
3
4
#!/usr/bin/perl -w
 
# Print the version.
print "Perl ".$]."\n";

The first line lets you call the program without prefacing the perl program because it invokes a subshell of perl by default. You just need to ensure the file has read and execute privileges to run. It prints:

Perl 5.018004

You need to install the perl-DBD-MySQL library to enable Perl to work with MySQL. The following command loads the library:

yum install -y perl-DBD-MySQL

It prints the following log file:

Loaded plugins: langpacks, refresh-packagekit
Resolving Dependencies
--> Running transaction check
---> Package perl-DBD-MySQL.x86_64 0:4.024-1.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package               Arch          Version                Repository     Size
================================================================================
Installing:
 perl-DBD-MySQL        x86_64        4.024-1.fc20           fedora        142 k
 
Transaction Summary
================================================================================
Install  1 Package
 
Total download size: 142 k
Installed size: 332 k
Downloading packages:
perl-DBD-MySQL-4.024-1.fc20.x86_64.rpm                      | 142 kB  00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : perl-DBD-MySQL-4.024-1.fc20.x86_64                           1/1 
  Verifying  : perl-DBD-MySQL-4.024-1.fc20.x86_64                           1/1 
 
Installed:
  perl-DBD-MySQL.x86_64 0:4.024-1.fc20                                          
 
Complete!

The following item_query.pl Perl program is consistent with the PHP, Python, and Ruby examples provided in other blog posts. It shows you how to use the Perl DBI library to query and return a data set.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/perl -w
 
# Use the DBI library.
use DBI;
use strict;
use warnings;
 
# Create a connection.
my $dbh = DBI->connect("DBI:mysql:database=studentdb;host=localhost:3306","student","student",{'RaiseError' => 1});
 
# Create SQL statement.
my $sql = "SELECT item_title FROM item";
 
# Prepare SQL statement.
my $sth = $dbh->prepare($sql);
 
# Execute statement and read result set.
$sth->execute() or die $DBI::errstr;
while (my @row = $sth->fetchrow_array()) {
  my $item_title = $row[0];
  print "$item_title\n";
}
 
# Close resources.
$sth->finish();

You call it like this from the present working directory:

./mysql_query.pl

It returns:

The Hunt for Red October
Star Wars I
Star Wars II
Star Wars II
Star Wars III
The Chronicles of Narnia
RoboCop
Pirates of the Caribbean
The Chronicles of Narnia
MarioKart
Splinter Cell
Need for Speed
The DaVinci Code
Cars
Beau Geste
I Remember Mama
Tora! Tora! Tora!
A Man for All Seasons
Hook
Around the World in 80 Days
Harry Potter and the Sorcerer's Stone
Camelot

Alternatively, there’s a different syntax for lines 20 and 21 that you can use when you’re returning multiple columns. It replaces the two statements inside the while loop as follows:

20
21
  my ($item_title, $item_rating) = @row;
  print "$item_title, $item_rating\n";

It returns:

The Hunt for Red October, PG
Star Wars I, PG
Star Wars II, PG
Star Wars II, PG
Star Wars III, PG13
The Chronicles of Narnia, PG
RoboCop, Mature
Pirates of the Caribbean, Teen
The Chronicles of Narnia, Everyone
MarioKart, Everyone
Splinter Cell, Teen
Need for Speed, Everyone
The DaVinci Code, Teen
Cars, Everyone
Beau Geste, PG
I Remember Mama, NR
Tora! Tora! Tora!, G
A Man for All Seasons, G
Hook, PG
Around the World in 80 Days, G
Harry Potter and the Sorcerer's Stone, PG
Camelot, G

As always, I hope this helps those learning how to use Perl and Linux against the MySQL Database. If you want a nice tutorial on Perl and MySQL, check The tutorialspoint.com web site.

Written by maclochlainn

April 13th, 2015 at 2:14 am

Python-MySQL Program

with 4 comments

This post works through the Python configuration of Fedora instance, and continues the configuration of my LAMP VMware instance. It covers how you add the MySQL-python libraries to the Fedora instance, and provides the students with one more language opportunity for their capstone lab in the database class.

A standard Fedora Linux distribution installs Python 2.7 by default. Unfortunately, the MySQL-python library isn’t installed by default. You can verify the Python version by writing and running the following version.py program before installing the MySQL-python library:

1
2
3
4
5
# Import sys library.
import sys
 
# Print the Python version.
print sys.version

You can run the version.py program dynamically like this from the current working directory:

python version.py

It will print the following:

2.7.5 (default, Nov  3 2014, 14:26:24) 
[GCC 4.8.3 20140911 (Red Hat 4.8.3-7)]

If you modify the program by adding the following first line

1
2
3
4
5
6
7
#!/usr/bin/python
 
# Import sys library.
import sys
 
# Print the Python version.
print sys.version

Provided you’ve set the file permissions to read and execute, you can run the program by simply calling version.py like this from the present working directory:

./version.py

You can install the MySQL-python library with the yum utility like this:

yum install -y MySQL-python

It shows you the following output:

Loaded plugins: langpacks, refresh-packagekit
mysql-connectors-community                                  | 2.5 kB  00:00     
mysql-tools-community                                       | 2.5 kB  00:00     
mysql56-community                                           | 2.5 kB  00:00     
pgdg93                                                      | 3.6 kB  00:00     
updates/20/x86_64/metalink                                  |  12 kB  00:00     
updates                                                     | 4.9 kB  00:00     
updates/20/x86_64/primary_db                                |  13 MB  00:04     
(1/2): updates/20/x86_64/updateinfo                         | 1.9 MB  00:02     
(2/2): updates/20/x86_64/pkgtags                            | 1.4 MB  00:02     
Resolving Dependencies
--> Running transaction check
---> Package MySQL-python.x86_64 0:1.2.3-8.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package              Arch           Version               Repository      Size
================================================================================
Installing:
 MySQL-python         x86_64         1.2.3-8.fc20          fedora          82 k
 
Transaction Summary
================================================================================
Install  1 Package
 
Total download size: 82 k
Installed size: 231 k
Downloading packages:
MySQL-python-1.2.3-8.fc20.x86_64.rpm                        |  82 kB  00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : MySQL-python-1.2.3-8.fc20.x86_64                             1/1 
  Verifying  : MySQL-python-1.2.3-8.fc20.x86_64                             1/1 
 
Installed:
  MySQL-python.x86_64 0:1.2.3-8.fc20                                            
 
Complete!

After installing the MySQL-python library, you can call the following mysql_connect.py program from the local directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python
 
# Import sys library.
import MySQLdb
import sys
 
try:
  # Create new database connection.
  db = MySQLdb.connect('localhost','student','student','studentdb')
  # Query the version of the MySQL database.
  db.query("SELECT version()")
  # Assign the query results to a local variable.
  result = db.use_result()
  # Print the results.
  print "MySQL Version: %s " % result.fetch_row()[0]
except MySQLdb.Error, e:
  # Print the error.
  print "ERROR %d: %s" % (e.args[0], e.args[1])
  sys.exit(1)
finally:
  # Close the connection when it is open.
  if db:
    db.close()

Like the version.py program, set the file permissions to read and execute and call , you can run the program by simply calling mysql_connect.py program like this from the present working directory:

./mysql_connect.py

The mysql_connect.py program displays:

MySQL Version: 5.6.24

After verifying the MySQL connection, you can query actual data with the following mysql_queryset.py program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/python
 
# Import sys library.
import MySQLdb
import sys
 
try:
  # Create new database connection.
  db = MySQLdb.connect('localhost','student','student','studentdb')
  # Create a result set cursor.
  rs = db.cursor()
  rs.execute("SELECT item_title FROM item")
  # Assign the query results to a local variable.
  rows = rs.fetchall()
  # Print the results.
  for row in rows:
    print row
except MySQLdb.Error, e:
  # Print the error.
  print "ERROR %d: %s" % (e.args[0], e.args[1])
  sys.exit(1)
finally:
  # Close the connection when it is open.
  if db:
    db.close()

You call the mysql_queryset.py file from the present working directory like this:

./mysql_queryset.py

It prints the following:

('The Hunt for Red October',)
('Star Wars I',)
('Star Wars II',)
('Star Wars II',)
('Star Wars III',)
('The Chronicles of Narnia',)
('RoboCop',)
('Pirates of the Caribbean',)
('The Chronicles of Narnia',)
('MarioKart',)
('Splinter Cell',)
('Need for Speed',)
('The DaVinci Code',)
('Cars',)
('Beau Geste',)
('I Remember Mama',)
('Tora! Tora! Tora!',)
('A Man for All Seasons',)
('Hook',)
('Around the World in 80 Days',)
("Harry Potter and the Sorcerer's Stone",)
('Camelot',)

You can substantially improve on the behavior of the prior example by handling each row one at a time. The following mysql_query.py program reads through the cursor result set one row at a time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/python
 
# Import sys library.
import MySQLdb
import sys
 
try:
  # Create new database connection.
  db = MySQLdb.connect('localhost','student','student','studentdb')
  # Create a result set cursor.
  rs = db.cursor()
  rs.execute("SELECT item_title FROM item")
  # Assign the query results to a local variable.
  for i in range(rs.rowcount):
    row = rs.fetchone()
    print row[0]
except MySQLdb.Error, e:
  # Print the error.
  print "ERROR %d: %s" % (e.args[0], e.args[1])
  sys.exit(1)
finally:
  # Close the connection when it is open.
  if db:
    db.close()

You call the mysql_query.py with the following syntax:

./mysql_query.py

It returns the following result set:

The Hunt for Red October
Star Wars I
Star Wars II
Star Wars II
Star Wars III
The Chronicles of Narnia
RoboCop
Pirates of the Caribbean
The Chronicles of Narnia
MarioKart
Splinter Cell
Need for Speed
The DaVinci Code
Cars
Beau Geste
I Remember Mama
Tora! Tora! Tora!
A Man for All Seasons
Hook
Around the World in 80 Days
Harry Potter and the Sorcerer's Stone
Camelot

As always, I hope this helps those looking for this type of solution. The Python tutorial web site teaches you more about the Python Programming Language. You may also find the TutorialsPoint.com site useful while you’re learning and using Python. The MySQLdb User’s Guide teaches more about working writing Python-MySQL library. The MySQLdb implements the Python Database API Specification v2.0.

Written by maclochlainn

April 12th, 2015 at 6:36 pm

MySQL JSON Functions

with 3 comments

What the MySQL team is doing with JSON (JavaScript Object Notation) in MySQL 5.7 is great! The MySQL Server Blog (Rick Hillegas and Dag Wanvik) published two key articles about new JSON functions. If you don’t follow these, let me highlight them as a set:

Most folks know how important JSON is to web development. I like the following visual that highlights it. It was provided as a comment to this earlier Popular Programming Language post by Michael Farmer. Clearly, JavaScript is popular because it’s critical to effective web development. If you’re new to JSON, check out Adam Khoury’s JSON tutorial set on YouTube.

PopularCode2014

If you want the original graphic, you can find it here. It’s always to hard to keep up with the technology, isn’t it? :-)

Written by maclochlainn

April 11th, 2015 at 11:36 am