Tag Archives: oracle database

Differences in databases or from Oracle to MySQL

In the last couple of weeks we have integrated MySQL support for Razuna 1.1.3 and learned that MySQL and Oracle have sometimes different syntaxes and approaches to the same SQL language. We thought that some of you might be interested in these and have gathered the ones we stumbled upon.

This should serve as a reference and for some coding problems you might run into. Some parts of this post is taken directly from the MySQL documentation, because it fits the current context and some is our own.

Our setup was a MySQL Server 5.0.45 and all tables are using the InnoDB storage engine. On the Oracle database side we use the 10g R2 release.

We did not want to change any global MySQL settings and wanted to keep it by the default installation. In this regard you might read a topic that could have been solved by adding a global setting parameter.

1. In MySQL tables names are case-sensitive on Linux, but case-insensitive on Windows

We were very surprised to find out that MySQL is case-sensitive for table names (on Linux). Honestly, I never thought that MySQL would have done something like that. We know that there is a global setting to change this, but as a neutral product we wanted Razuna to support MySQL independently of the server settings.

2. Substitute NULL value

Oracle’s nvl() Function
In Oracle/PLSQL, the NVL function lets you substitute a value when a NULL value is encountered.

The syntax for the NVL function is:

NVL( string1, replace_with )

string1 is the string to test for a null value.

replace_with is the value returned if string1 is null.

For example:

select nvl(supplier_city, 'n/a') from suppliers;

Mysql’s ifnull() Function
In MySQL, you can use IFNULL() in your SELECT statement is make the NULL any value you wish.

The syntax for the IFNULL function is:

IFNULL(expr1,expr2)

If expr1 is not NULL, IFNULL() returns expr1, else it returns expr2.

For example:
select ifnull(supplier_city, ‘n/a’) from suppliers;

If expr is given as an argument to LAST_INSERT_ID(), the value of the argument is returned by the function and is remembered as the next value to be returned by LAST_INSERT_ID(). This can be used to simulate sequences:

  1. Create a table to hold the sequence counter and initialize it:
    mysql> CREATE TABLE sequence (id INT NOT NULL);
    mysql> INSERT INTO sequence VALUES (0);
  2. Use the table to generate sequence numbers like this:
    mysql> UPDATE sequence SET id=LAST_INSERT_ID(id+1);
    mysql> SELECT LAST_INSERT_ID();

The UPDATE statement increments the sequence counter and causes the next call to LAST_INSERT_ID() to return the updated value. The SELECT statement retrieves that value. The mysql_insert_id() C API function can also be used to get the value. See Section 19.7.3.37, “mysql_insert_id().

You can generate sequences without calling LAST_INSERT_ID(), but the utility of using the function this way is that the ID value is maintained in the server as the last automatically generated value. It is multi-user safe because multiple clients can issue the UPDATE statement and get their own sequence value with the SELECT statement (or mysql_insert_id()), without affecting or being affected by other clients that generate their own sequence values.

3. ERROR 1170 (42000): BLOB/TEXT column ‘field_name’ used in key specification without a key length

The error happens because MySQL can index only the first N chars of a BLOB or TEXT column. So, the error mainly happen when there is a field/column type of TEXT or BLOB or those belongs to TEXT or BLOB types such as TINYBLOB, MEDIUMBLOB, LONGBLOB, TINYTEXT, MEDIUMTEXT, and LONGTEXT that you try to make as primary key or index. With full BLOB or TEXT without the length value, MySQL is unable to guarantee the uniqueness of the column as it’s of variable and dynamic size. So, when using BLOB or TEXT types as index, the value of N must be supplied so that MySQL can determine the key length. However, MySQL doesn’t support limit on TEXT or BLOB. TEXT(88) simply won’t work.

The error will also pop up when you try to convert a table column from non-TEXT and non-BLOB type such as VARCHAR and ENUM into TEXT or BLOB type, with the column already been defined as unique constraints or index. The Alter Table SQL command will fail.

The solution to the problem is to remove the TEXT or BLOB column from the index or unique constraint, or set another field as primary key. If you can’t do that, and wanting to place a limit on the TEXT or BLOB column, try to use VARCHAR type and place a limit of length on it. By default, VARCHAR is limited to a maximum of 255 characters and its limit must be specified implicitly within a bracket right after its declaration, i.e VARCHAR(200) will limit it to 200 characters long only.

Sometimes, even though you don’t use TEXT or BLOB related type in your table, the Error 1170 may also appear. It happens in situation such as when you specify VARCHAR column as primary key, but wrongly set its length or characters size. VARCHAR can only accepts up to 256 characters, so anything such as VARCHAR(512) will force MySQL to auto-convert the VARCHAR(512) to a SMALLTEXT datatype, which subsequently fail with error 1170 on key length if the column is used as primary key or unique or non-unique index. To solve this problem, specify a figure less than 256 as the size for VARCHAR field.

Note that mysql_insert_id() is only updated after INSERT and UPDATE statements, so you cannot use the C API function to retrieve the value for LAST_INSERT_ID(expr) after executing other SQL statements like SELECT or SET.

Not only that, but by default windows mysql converts table names to lower case on sql dump restores. Watch out for that gotcha.

4. Nested Selects need an alias

Select field
from (
select test
from test
) ALIAS

Oracle does not need the alias, but MySQL will throw you a error if you don’t have an alias set!

5. ROWNUM in MySQL

The ROWNUM is badly missed in MySQL. But we have found something similar.

Oracle:
select rownum, foo from bar where rownum<5;

MySQL:
select @n:=@n+1, foo from bar where @N<5;

or (a simpler solution):

select foo from bar LIMIT 0,20;

6. Delete from with exists

One thing that hit us hard was that within Oracle you can use the same table within a subquery when doing a delete. When does this matter, you might ask? Look at the following code example:

DELETE FROM t1
WHERE id = 1
AND EXISTS ( SELECT * FROM t2, t1 WHERE … )

This is a valid syntax with Oracle, but this will throw a error with MySQL saying “You can’t specify target table ‘t1′ for update in FROM clause”. Of course, you could argue which one is right, but that is not the matter of this post.

The workaround for the above is to either get your syntax correct (by NOT using the same table again within the subquery) or then use INNER JOIN. Another workaround (as by the comment in the MySQL documentation) is to use temporary tables.

7. Constraints

Now the CONSTRAINTS hit us quite hard (again). As one could easily create constraints with Oracle, we were forced to have INNODB tables and each related key has to have a index to work! There are more requirements that have to be meet with MySQL for constraints to work. Best is to read it up at their Foreign Key Constraint documentation site.

Also, when you try to DROP a table then watch out for this “behaviour”;

InnoDB does not allow you to drop a table that is referenced by a FOREIGN KEY constraint, unless you do “SET foreign_key_checks = 0″. When you drop a table, the constraints that were defined in its create statement are also dropped.

8. Cast Types

Oracle allows VARCHAR(n) within a Cast. MySQL does not and you need to replace VARCHAR(n) with CHAR(n). MySQL documentation for CAST.

9. Concat differences

Concat is another syntax that Oracle handles completely different then MySQL. Look at this Oracle code:

SELECT NVL(t1.fieldid, ‘myfield’ || CAST(t2.order AS VARCHAR(1000))) as char(1000))) AS fieldid
FROM …..

Given this is a more complex example, but it shows you how you can “concat” and use cast at the same time to combine a field and assign this to an alias.

Now with MySQL the above will have to be like;

SELECT IFNULL(t1.fieldid, CAST(CONCAT(‘myfield’,t2.order) as CHAR(1000))) AS fieldid
FROM …..

So, this is our list of the things we run into while adding support for MySQL to our open source Digital Asset Management Razuna. Did we forget something or have you encountered other things you would like to share? Don’t hesitate let us know in the comment section.

Comments { 43 }

Razuna 1.1, open source digital asset management, now available

We are very happy to announce that Version 1.1 of Razuna – our open source Digital Asset Management System with integrated Web Content Management – is now available (and this on the day that Elvis died and Madonna turns 50)!

Version 1.1 features a embedded database that lets you deploy Razuna within minutes and without any additional database setup. The embedded database performs very well and holds up in production environments as well. Of course, support for the Oracle database is still given.

We also increased the speed on some asset operations and make now extensive use of the Lucene search engine. Additionally we included a Upgrade Manager, which makes upgrading to a new version a breeze. For the CMS part we updated FCKEditor to release 2.6.3 which fixes some issues that users experienced on Firefox 3.

This release of Razuna is a major leap for us, since we have now transitioned to a complete Open Source distribution, where all components used are now open sourced. For the technically inclined Razuna leverages the following open source components; OpenBD (Lucene included), Tomcat and H2 (I am going to blog some more about this database). As always, this release comes as a WAR/EAR distribution or bundled with Tomcat as a Standalone Server.

Razuna is a professional digital asset management/media asset management with an integrated web content management that delivers and makes management of your digital assets a simple task. Razuna is licensed under a dual-license (AGPL and commercial) and can be downloaded at http://www.razuna.com. The Wiki is available at http://wiki.sixsigns.com and the public Issues Tracker at http://issues.sixsigns.com (both products proudly sponsored by Atlassian (Confluence and Jira) ).

(We are aware that our forum is down right now. We should be up and running on Monday again. Thank you for all your patience.)

Comments { 54 }

Installing Oracle database 11g should not be a nightmare, right?

Ok, first of I want to say that I have installed quite a couple of Oracle database releases and that I am not a newbie to this, but today I feel like one. Why? Well, simply put, I don’t understand how Oracle can release a product that is full of bugs and misplaced links. Anyhow, let’s get started:

Yesterday we thought of installing the latest and greatest Oracle database 11gR1 release on our brand new shiny Linux box. As always we are using the brilliant CentOS 5. We then went ahead and did step by step according to the installation instructions of this Oracle guide to install 11g on Linux.

All went fine until the Database Configuration Assistance came up with an error that it can not install properly. It also said that this is not so bad as one can run the installation manually later on. We have had these errors in the past and know how to handle them. Thus we continued. After that the database was setup fine.

Actually all went fine, we could login to the database without a problem and all is set. Well that means, the database was running, but no the listener! More to that later on.

We then configured the system to start the Oracle services automatically on reboot. For that we used another Oracle Guide that is supposed to state the correct settings. The problem is that it does NOT work as stated in their document!

First thing is to go into “# vi /etc/oratab” and edit the last line of the string to change it to a “Y” instead of the “N”. No problem, but it gets problematic when you are trying to use the “dbora” script. Because as soon as you are trying “/sbin/chkconfig –level 345 dbora on” (this has to be done on CentOS/RedHat) you will get an error like “service dbora does not support chkconfig”. How come?

To make the script “dbora” work on CentOS/RedHat you will want to include this at the top of the document:

#!/bin/sh
# chkconfig: 345 99 10
# description: Oracle auto start-stop script.

The important part here is to have the line “chkconfig” AND “description” in the file. Otherwise “chkconfig” will not work! Ok, on with the show.

Still after reboot the database does not come up as expected. Digging around some more, we found that the script “dbstart” has another bug. This line:

# First argument is used to bring up Oracle Net Listener
ORACLE_HOME_LISTNER=$1

does NOT work! As soon as one changes it to the actual path of the installation the script runs much better. So go ahead and change it to:

# First argument is used to bring up Oracle Net Listener
ORACLE_HOME_LISTNER=/opt/oracle/product/11.1.0/db_1

Of course, our Oracle installation is under “/opt”, change this to your installation path. Some have posted in blogs and forums that you could also change it to “$ORACLE_HOME” but we have had no success with that only the hard coded path value does work.

Fun, isn’t it? But wait there is more and make sure to read until the end of this post. Next up is not really something that os Oracle’s fault, but never the less not stated anywhere. To make working in the shell more comfortable and that the scripts DO work you will want to modify your “profile” settings.

Fire up “vi” and edit “/etc/profile” and add the following lines (change it to fit your path and SID):

PATH=$PATH:/opt/oracle/product/11.1.0/db_1/bin
ORACLE_HOME=/opt/oracle/product/11.1.0/db_1/
ORACLE_SID=orcl
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC ORACLE_HOME ORACLE_SID

Ok, after you have done all of the above you can safely restart your machine and your Oracle database should start automatically. If it does not then a “dbca” could help. but wait, I kept the best for the end!

In our installation we have found that with the scripts above any local login to the sqlplus console reports us that we are connected to an idle instance! But, now get this, my users can login to the database with SQL-Developer or any remote client!!! Don’t believe us, here is the screen shot of the local login:

oracle11g.png

Only this “little” thing kept us quite busy for today and it is leaving a feeling that Oracle database 11gR1 might not be so ready for big time yet. But maybe we are doing something wrong? Let us know, we are welcome to suggestions.

Comments { 57 }