Archive for the ‘Oracle’ Category
Oracle XE Gateway Debug Mode
When developing Web applications using Oracle XE and the embedded PL/SQL gateway, you may find that debugging is a pain due to the lack of log files (like you’d normally find in Apache folders in a full Oracle application server install). Well, the good news is, that you can configure errors to be reported directly in the browser, so that rather than getting very unhelpful 404 and other HTTP error messages, you get a full debug trace of the error that occurred. Full credit for this find goes to Dietmar Aust, who has a great blog on Oracle XE and Application Express. See his original post for even more insight into this.
To switch on error reporting and the printing of debug messages to the browser, simply issue the following commands. Of course, be sure to replace “embosa” on line 3 with your own DAD name. Also, be sure to turn this back off again in a production environment, this should only be used for development and testing purposes.
begin
dbms_epg.set_global_attribute('log-level', 3);
dbms_epg.set_dad_attribute('embosa', 'error-style', 'DebugStyle');
end;
/
To test, simply go to a URL that doesn’t exist, and you should see a useful error message instead of a unhelpful “Not Found” message. See the screenshot below for an example of what this error message looks like.
Tags in Oracle Nested Tables
Tags are a useful means of associating keyword metadata with a data structure such as an image, a video, audio or a piece of text. There are many ways of storing tags in a database – for example one could store a string of tags separated by a space, comma or semi-colon. Alternatively, one could store tags in a database table and then create another table to hold the list of tags for a given entity. My preferred method of storing tags, in an Oracle database at least, is to use the concept of nested tables.
Nested tables are a type of PL/SQL collection which may be compared to arrays or objects in other programming languages. One of the advantages of using nested tables over other PL/SQL collection types is that they don’t have a fixed size, and they can be stored in a database table (not just in a program unit, like regular PL/SQL tables or associative arrays). The best way to show how nested tables work is to use an example, so let’s dive right in and set up our database for the tags example.
The first thing we want to do is create the nested table type in our database. I’m going to keep it nice and simple and name my type “tags”:
CREATE TYPE tags IS TABLE OF VARCHAR2(50);
If you are familiar with PL/SQL tables, the above should look very similar to the syntax for creating a PL/SQL table, but without the typical “index by binary_integer” bit stuck at the end. With our type created, we can now go ahead and use this in a database table. I’m going to create a table named “post”, which one might use to store blog posts. This table will have three columns – post_id, post_title and post_tags.
CREATE TABLE post (
post_id           NUMBER(11),
post_title       VARCHAR2(50),
post_tags       tags
) NESTED TABLE post_tags STORE AS tags_table;
Great – you now have a database table with a column of type “tags” which is itself a table. The next thing we want to do is insert some records into our new table.
INSERT INTO post(post_id, post_title, post_tags)
VALUES(1, 'First Post', tags('oracle', 'tags', 'example'));
INSERT INTO post(post_id, post_title, post_tags)
VALUES(2, 'Second Post', tags('oracle', 'tags'));
INSERT INTO post(post_id, post_title, post_tags)
VALUES(3, 'Third Post', tags('oracle'));
COMMIT;
As you can see from the above INSERT statements, inserting tags into our nested table is very straightforward, we simply tell Oracle that we are using the type “tags” and pass the VARCHAR2 values we want to store to it. If you try to insert a tag with over 50 characters you will get an error as we defined the tags table as a table of VARCHAR2(50) fields. So what does our new table look like when we go to retrieve data from it? Let’s take a look.
SELECT * FROM post;
You should see output like the following
POST_ID POST_TITLE                                               POST_TAGS ------------ ----------------------------------------------------------- --------- 1 First Post                                                 <Object> 2 Second Post                                                <Object> 3 Third Post                                                 <Object>
Hardly ideal is it? Fortunately, we can use the TABLE function to easily get back a list of tags for a given post quite easily. Try the following SQL statement:
SELECT column_value
FROM TABLE(
SELECT post_tags FROM post WHERE post_id = 1
);
This outputs the following:
COLUMN_VALUE -------------------------------------------------- oracle tags example
Try the statement again, but this time pass in the post_id value for another row. This is useful, as it gives us a means of getting the tag data out of the database, but what if we want to get back all the tags when retrieving the other columns in the table? This requires a bit more work, but it’s not exactly complex:
SELECT p.post_id, p.post_title, t.column_value
FROM post p, TABLE(
SELECT post_tags FROM post WHERE post_id = p.post_id
) t;
The above statement should produce the following:
POST_ID POST_TITLE                                             COLUMN_VALUE ------------ ------------------------------------------------------- --------------- 1 First Post                                             oracle 1 First Post                                             tags 1 First Post                                             example 2 Second Post                                           oracle 2 Second Post                                            tags 3 Third Post                                            oracle
A step in the right direction, but the post_id and post_title are duplicated for each tag for that record. Surely there’s a way of outputting all the tags on a single row, joining them together with a delimiting character such as a comma? There are a number of ways of doing this, from using a stored function to using 11g’s WITHIN GROUP feature. The method with the least code that works on 9i and above is to use the XMLAGG function to produce the concatenated result. The SQL to achieve the desired result in this manner is as follows:
SELECT p.post_id, p.post_title,
RTRIM(XMLAGG(XMLELEMENT(e, t.column_value || ',')).EXTRACT('//text()'), ',') tags
FROM post p, TABLE(
SELECT post_tags FROM post WHERE post_id = p.post_id
) t
GROUP BY p.post_id, p.post_title;
This produces the following result:
POST_ID POST_TITLE                              TAGS ------------ ---------------------------------------- ----------------------- 1 First Post                              oracle,tags,example 2 Second Post                             oracle,tags 3 Third Post                              oracle
So far we haven’t seen any particular reason why one would necessarily use a nested table to store tags over any other method. For me, the primary advantage is that it makes it very simple to perform group functions on the tags – making it ridiculously easy to generate tag clouds based on how many times a tag is used. In the above example, we can easily see that the tag “oracle” is used 3 times, “tags” is used twice and “example” only once. But in a scenario where you have many posts and many, many tags, it is impossible to do this counting in your head. Let’s take a look at just how easy it is to do this counting with our nested table.
SELECT t.column_value, COUNT(*)
FROM post p, TABLE(
SELECT post_tags FROM post WHERE post_id = p.post_id
) t
GROUP BY t.column_value;
And the output:
COLUMN_VALUE                                        COUNT(*) -------------------------------------------------- ---------- tags                                                       2 example                                                    1 oracle                                                     3
Want to order the results? Simply add an ORDER BY clause and Bob’s your uncle.
SELECT t.column_value, COUNT(*)
FROM post p, TABLE(
SELECT post_tags FROM post WHERE post_id = p.post_id
) t
GROUP BY t.column_value
ORDER BY 2 DESC;
The result:
COLUMN_VALUE                                        COUNT(*) -------------------------------------------------- ---------- oracle                                                     3 tags                                                       2 example                                                    1
For me, this is the main reason I store tags in a nested table – but there are other advantages, too. What if you are editing a post and you want to change one of the tags? Nested tables make this simple:
UPDATE TABLE(SELECT post_tags FROM post WHERE post_id = 1) SET column_value = 'sample' WHERE column_value = 'example'
Similarly, if you wanted to delete a tag from a row, this is also very straightforward:
DELETE FROM TABLE(
SELECT post_tags FROM post WHERE post_id = 1
)
WHERE column_value = 'tags';
Nested tables are a powerful PL/SQL collection type, and you can do even more powerful things with them if you start using PL/SQL procedures and functions. But the beauty about nested tables for me is how powerful and flexible they are using nothing but raw SQL statements. For further information about nested tables and other PL/SQL collection types, see the following resources:
- http://www.developer.com/db/article.php/10920_3379271_1/Oracle-Programming-with-PLSQL-Collections.htm
- http://www.dba-oracle.com/t_display_multiple_column_values_same_rows.htm
- http://www.devshed.com/c/a/Oracle/Database-Interaction-with-PLSQL-Nested-Tables/
- http://soft.buaa.edu.cn/oracle/bookshelf/Oreilly/prog2/ch19_01.htm
- http://sql-plsql.blogspot.com/2007/05/oracle-plsql-nested-tables.html
- http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/05_colls.htm
- http://www.smart-soft.co.uk/Oracle/oracle-plsql-tutorial-part-9.htm
Oracle XE and mod_plsql
In this post you will learn how to get a sandboxed PL/SQL web development environment up and running on a Windows machine. You will use the VMware Player virtualization system to run an Ubuntu 9.10 server image, on which you will install Oracle XE. You will then configure a DAD using DBMS_EPG which basically acts in the same way as mod_plsql does in Oracle HTTP Server. This will allow you to create Web applications using PL/SQL. Finally, you will learn how to work with virtual directories so you can store things like images, external stylesheets and external JavaScript files.
The first step you need to follow is to download and install the free VMware Player application on your system. This can be downloaded from https://www.vmware.com/tryvmware/?p=player&lp=1. Once this has downloaded, follow the simple instructions to install VMware Player. This application allows you to run other operating systems that are packaged in virtual machine images. Head over to http://www.thoughtpolice.co.uk/vmware/#ubuntu9.10 and download the appropriate image for Ubuntu 9.10 Karmic Koala. When this has finished downloading, extract the files to a convenient location on your file system, and find the file ubuntu-server-9.10-i386.vmx, and double-click it to start the virtual machine.
At this point, VMware Player should open and your Ubuntu VM will launch and boot up. After a few moments, you should see a prompt like the one shown in Figure 1:

Figure 1 - Ubuntu Login Prompt
To login, enter the login notroot and the password thoughtpolice. You will now be logged in and should see the Ubuntu shell prompt.
By default, the VM image you are using has 905208 bytes of swap space allocated. Unfortunately, this will cause the Oracle XE installer to fail, as its minimum is 1024MB. To prevent this from happening, you first need to assign some more swap space. Use the following commands to bump up the swap space to 1058800 bytes. If you are asked for your [sudo] password for notroot (you will be), enter thoughtpolice.
$ sudo dd if=/dev/zero of=/tmp/swap bs=1M count=150 $ sudo mkswap /tmp/swap $ sudo swapon /tmp/swap $ free
If the commands worked correctly, the output from the free command should look similar to the results shown in Figure 2 below:

Figure 2 - Configuring swap space
With the swap space issue resolved, you can now move on to the steps required to download, install and configure Oracle XE. First, you’ll need to add the Oracle repository to your apt sources list. Issue the following command to open the list in the nano text editor:
$ sudo nano /etc/apt/sources.list
Navigate to the end of this file (use Ctrl+V to scroll down page by page) and at the bottom add the following line:
deb http://oss.oracle.com/debian unstable main non-free
Save the file by pressing Ctrl+O, and then exit using Ctrl+X.
Now you can go ahead and download Oracle XE using the following commands:
$ wget http://oss.oracle.com/el4/RPM-GPG-KEY-oracle -O- | sudo apt-key add - $ sudo apt-get update $ sudo apt-get install oracle-xe
This process may take some time (XE is a 221MB package) and you may need to answer Y when asked if you wish to continue.
It’s worth pointing out that when I ran the above commands, I found that the download would sometimes freeze at a certain point. If this happens to you, press Ctrl+C to force exit the process and then re-issue the command to pick up from where you left off (you can press the up arrow key to quickly bring up the last command you entered).
When the process has finished, Oracle XE is now installed. Before you can use it, however, you will need to configure it. Issue the following command to start the Oracle Database configuration tool:
$ sudo /etc/init.d/oracle-xe configure
When asked for a port number for Application Express, accept the default option of 8080 by pressing Enter. Do the same when offered port 1521 for the database listener. Next, enter a system password, and confirm it when requested. Finally, accept the default setting of y when asked if you want XE to be started on boot. Oracle will now configure the Net Listener and the Database – this may take a few minutes. When it is done you should see a message like the one shown in Figure 3.

Figure 3 - Oracle install complete
The next step you need to follow is to set up the ORACLE_HOME and PATH variables on your system, which will make it easier to run the SQL*Plus client. Create your user .bash_profile file by issuing the following commands:
$ cd ~ $ nano .bash_profile
In the nano editor, insert the following two lines:
export ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
export PATH=${PATH}:${ORACLE_HOME}/bin
Press Ctrl+O to save and then Ctrl+X to quit nano. Now, log out of Ubuntu using the following command:
$ logout
You’ll be returned to the login prompt. Login once again using the username notroot and password thoughtpolice. Now, issue the following command to start the SQL*Plus client as the SYSTEM user:
$ sqlplus system@xe
Enter the password you chose when configuring Oracle when requested at the prompt. You should then see a message informing you that you are connected to Oracle. Now that you are logged in to the database, it is a good time to allow remote access to the Oracle XE web server, which runs Apex and which we will be using to run our PL/SQL web applications. To do this, issue the following command:
SQL> exec dbms_xdb.setlistenerlocalaccess(false);
You should see the message “The PL/SQL procedure successfully completed.” before being returned to the SQL prompt. Next, exit SQL*Plus by entering the following command:
SQL> exit
You will now be back at the Ubuntu shell prompt. The next thing you’ll need to do is determine the IP address of your virtual machine. To do this, use the command:
$ ifconfig
You should see output similar to the one shown below. You need to look for the entry for eth0, specifically for the value next to inet addr: – in my case it is 192.168.133.131, as shown in the screenshot in Figure 4.

Figure 4 - VM IP address
Now, back in Windows, fire up your favourite Web browser and enter the following address into the Address box, replacing my IP address with the one for your virtual machine:
http://192.168.133.131:8080/apex
You should see a screen like the one shown in Figure 5.

Figure 5 - Oracle Application Express Home Page
This interface is actually very useful, so let’s login and create a new database user, which you will later use as the schema for your PL/SQL web application. Enter the username SYSTEM and the password you entered during the Oracle configuration. From the next screen, click the arrow next to the Administration icon, and from the Database Users menu, select “Create User”. This will bring you to a form where you can enter the details for the new database user. Enter the username embosa and whatever password you like (for the sake of simplicity it would be wise to use the same password as you chose for the SYSTEM user – of course you would never do this on a production system!). Make sure that the roles CONNECT, RESOURCE and DBA are all checked, and press the “Create” button at the top right hand side of the form to create the user.
Next, hop back to your Ubuntu VM and enter the following command to login to Oracle using your new user:
$ sqlplus embosa@xe
Enter the password when asked, and hey presto, you’re logged in as the user embosa! Now, let’s go about creating a DAD so that we can publish HTML using PL/SQL. The following block of code will create, authorize and configure a DAD named embosa which will be accessible at the URL http://192.168.133.131:8080/embosa (again, replace the IP address with your own VM’s IP).
begin dbms_epg.create_dad(dad_name=>'embosa', path=>'/embosa/*'); dbms_epg.authorize_dad(dad_name=>'embosa', user=>'EMBOSA'); dbms_epg.set_dad_attribute(dad_name=>'embosa', attr_name=>'default-page', attr_value=>'home'); dbms_epg.set_dad_attribute(dad_name=>'embosa', attr_name=>'database-username', attr_value=>'EMBOSA'); end; /
This will create the DAD, next you need to create the “default page” by creating a procedure named home. To do so, use the following:
create or replace procedure home as
begin
htp.p('Hello, world!');
end home;
/
Now, hop back over to Windows and in your Web browser, navigate to the URL http://192.168.133.131:8080/embosa, replacing the IP address accordingly. You should see something like that shown in Figure 6.

Figure 6 - A basic PL/SQL Web Application
The final piece of configuration to do is to configure a virtual directory where you can store images, external styles and scripts and so on. Back in your Ubuntu VM, you should still be logged into SQL*Plus. In here, run the following command to open port 2100 for FTP connections:
SQL> exec dbms_xdb.setftpport('2100');
Now, enter exit to leave SQL*Plus, and create a test text file by issuing the following command:
$ echo testing! > test.txt
Next enter the command ftp to open the FTP client. At the ftp prompt, issue the following commands (you will be prompted for your username and password, these are your database username and password, so if you followed the instructions above your username will be embosa):
ftp> open localhost 2100 ftp> ls ftp> mkdir images ftp> cd images ftp> send test.txt
Now, go back to your web browser, and this time enter the URL http://192.168.133.131:8080/images/test.txt (again, change the IP as required) -Â you should see the message “testing!”. That’s it, your virtual directory is now created and you can use your favourite FTP client to upload images and other files to this directory. To connect to this folder from Windows, just enter the Ubuntu VM’s IP as the hostname, be sure to enter 2100 as the port number, and use the database username and password to login.
You should now have a usable alternative to mod_plsql up and running, which will allow you to create PL/SQL web applications on Oracle XE alone. I hope to post some more tutorials in the near future that will capitalise on this setup, showing you how to create useful PL/SQL Web applications. If you have any questions, comments or suggestions, feel free to leave a comment on this post.
PL/SQL and the Twitter API
In this post, you will use the UTL_HTTP database package and the PL/JSON library to connect to the Twitter API and retrieve status updates from the Twitter microblogging service.
This post assumes you have access to an Oracle database with the UTL_HTTP package available (Oracle Database 10g Express Edition does) and that you have installed the PL/JSON library, a set of tools for working with JSON data in PL/SQL. For a guide to installing PL/JSON and getting to grips with the basics of the library, see this previous post.
The UTL_HTTP package is not usually granted to database users other than SYS, so the first step is to log on to your Oracle database as SYS and run the following command:
grant execute on utl_http to embosa;
Of course, be sure to replace “embosa” with your Oracle username. You should now have access to the UTL_HTTP package. Next, let’s verify that UTL_HTTP can connect to the Twitter API and return data from it. Execute the following PL/SQL block to do so:
declare
req utl_http.req;
resp utl_http.resp;
value varchar2(32767);
begin
req := utl_http.begin_request('http://api.twitter.com/1/statuses/public_timeline.json');
resp := utl_http.get_response(req);
loop
utl_http.read_line(resp, value, true);
dbms_output.put_line(substr(value, 1, 255));
end loop;
utl_http.end_response(resp);
exception
when utl_http.end_of_body then
utl_http.end_response(resp);
end;
/
This should return a response similar to the following:
[{"in_reply_to_user_id":67594046,"in_reply_to_status_id":null,"created_at":"Sat Feb 27 11:30:06 +0000 2010","favorited":false,"source":"web","geo":null,"in_reply_to_screen_name":"pemoutinho","truncated":false,"contributors":null,"user":{"geo_enabled":fals
Note that in the above example, the output has been trimmed down to 255 characters so that the DBMS_OUTPUT buffer would not overflow. In a moment you will parse the entire response as JSON and access individual properties using the PL/JSON library.
Now that you have verified that UTL_HTTP can connect to the Twitter API, let's parse the JSON and print out the status updates in a more meaningful format:
declare
req utl_http.req;
resp utl_http.resp;
value varchar2(32767);
jsonArray json_list;
jsonObj json;
begin
begin
req := utl_http.begin_request('http://api.twitter.com/1/statuses/public_timeline.json');
resp := utl_http.get_response(req);
utl_http.read_text(resp, value);
utl_http.end_response(resp);
exception
when utl_http.end_of_body then
utl_http.end_response(resp);
end;
jsonArray := json_list(value);
dbms_output.put_line('---------------------------------------------------------------');
for i in 1..jsonArray.count loop
jsonObj := json.to_json(jsonArray.get_elem(i));
dbms_output.put_line(json_ext.get_varchar2(jsonObj, 'text'));
dbms_output.put_line('Posted by ' ||json_ext.get_varchar2(jsonObj, 'user.screen_name'));
dbms_output.put_line('Posted on ' ||json_ext.get_varchar2(jsonObj, 'created_at'));
dbms_output.put_line('---------------------------------------------------------------');
end loop;
end;
/
In this example, you get the entire response from the Twitter API using UTL_HTTP.READ_TEXT, and parse it using PL/JSON's json_list object (as Twitter's API is a JSON array containing several JSON objects). You then loop through each item in this list, extracting the text, user screen name and created at properties for each status update and outputting them. Each tweet is separated by a line of hyphens to make it easier to read. The final output should look something like the following:
--------------------------------------------------------------- Am reading this blog and a girl mentione Habana Outpost. Oh Brooklyn, sometimes I miss you. though I heard Habana was wack now... Posted by thefashionbomb Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @0oo \u75b2\u308c\u3061\u3083\u3044\u307e\u3057\u305f\uff1f\u3061\u3087\u3063\u3068\u4f11\u307f\u307e\u3057\u3087\u3046\u304b Posted by naoko_bot Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @papodebola sobre o horario dos jogos em sampa, uma frase que todo politico teme: Ninguem aguentaria 15 min de fama no Jornal NacionalPosted by ReeFzera Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @abogado_kaito \u308f\u304b\u308c\u3070\u3044\u3044\u306e\u3088\uff01 Posted by renkon_0 Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- Just write something about Nicks cars:D Posted by love_ncarter Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @Reema226: The book store? Posted by amitgupta Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- \u3057\u304b\u3057TV\u306e\u30d6\u30e9\u30c7\u30a3\u30de\u30f3\u30c7\u30a4\u306f\u30d5\u30a1\u30eb\u30b3\u30f3\u5f31\u3044\u306a\u301c\u3002 Posted by kazuwitter Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- ya abisnya kamu rese di;iatin org tau
RT @ninomayday: yehee siapa suruh coba lagian maksa dasar lu yaang hahaha :p Posted by karinutriansyah Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- \u3053\u3046\u3044\u3046\u3053\u3068\u77e5\u3063\u3066\u308b\u304b\u3089\u306a\u306b\uff1f\u3063\u3066\u601d\u3044\u307e\u3059\u3002\u81ea\u5206\u306e\u884c\u52d5\u3068\u306e\u9023\u9396\u3092\u8003\u3048\u3082\u3057\u306a\u3044\u3067\u3002\u3042\u3068\u81ea\u5206\u306e\u56fd\u306e\u8ca7\u56f0\u3082\u77e5\u3089\u306a\u3044\u306e\u306b\u304b\u308f\u3044\u305d\u3046\u3068\u304b\u4e2d\u9014\u534a\u7aef\u3059\u304e\u308b\u3068\u601d\u3044\u307e\u3059\u3002RT @gaitifujiyama \u65e5\u30c6\u30ec\u306e\u4e16\u754c\u4e00\u53d7\u3051\u305f\u3044\u6388\u696d\u3001\u6642\u305f\u307e\u3044\u3044\u4e8b\u3084\u308b\u3093\u3060\u3088\u306d\u3002\u4eca\u3001\u6b63\u306b\u305d\u308c\u3084\u3063\u3066\u3044\u308b Posted by machuiii Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @_rica \uc544 \uc774\uac74 tiltshiftgen \uc774\ub77c\ub294 \uc571\uc758 \ud798\uc744 \ube4c\ub9b0 \uc870\uc791[..] \uc2e4\uc81c \uce74\uba54\ub77c\uc5d0\uc11c\ub294 \ud2f8\ud305 \ub80c\uc988\uac00 \uc774\ub7f0 \ubbf8\ub2c8\uc5b4\ucc98 \ud6a8\uacfc\ub97c \ub0b4\uc900\ub2e4\uace0 \ud558\ub354\uad70\uc694. Posted by jstrane Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @micaelquental, fala maluco,,, Posted by Jeankarllus Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- Ask me anything http://formspring.me/CassiGLAMOUR Posted by Cassi_Hopeful Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- I killed a plant, and I disliked it! Posted by Malantur Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- Can someone give me Ro's link to his page on here just with the @ so I get onto it since I can't do it on the search bar!? =/ x Posted by Feehilys_Angelx Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- RT @terrycavanagh: Really excited by the concept behind Jason Rohrer's new game - check it out: http://sleepisdeath.net/ Posted by sonneveld Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @zzz_ral \u53ef\u611b\u3044\u3001\u3063\u3066\u3044\u3046\u304b\u30a8\u30ed\u3044\u3001\u30c9\u30a8\u30ed\u3060\u3088\u306d\uff01 Posted by chamber11 Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @nano_limpid %\u8077\u306f\u5927\u5909\u3063\u3059\u306d\uff57\uff57\uff57\uff57\uff57 Posted by Syana Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- Aku suka perkataan cacu tadi sore... Posted by masagakenaldema Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @dildillaa dih pede geelaaahhh hahha Posted by satriavisabrina Posted on Sat Feb 27 11:55:17 +0000 2010 --------------------------------------------------------------- @555hamako \u3042\u307c\u30fc\u3093\u3068\u30ad\u30dc\u30f3\u30cc\u304c\u3054\u3063\u3061\u3083\u306b\u306a\u3063\u3066\u307e\u3059\u306d\u3048w\u3002 Posted by florestan854 Posted on Sat Feb 27 11:55:17 +0000 2010 ---------------------------------------------------------------
You may notice that some tweets seem to be made up of gibberish with \u all over the place. These are Unicode characters and usually represent non-Latin characters such as Chinese characters, which Twitter stores as Unicode.
There you have it, in this post you have created a basic Twitter public timeline reader using PL/SQL, the UTL_HTTP package and the PL/JSON library. It should be relatively straightforward to build on this foundation to create a more complete Twitter client using PL/SQL. For more information about the Twitter API see the official Twitter API wiki.
Oracle and JSON: Using PL/JSON
JSON (JavaScript Object Notation) is a lightweight data format that is very well suited for transmitting data over the Internet. Despite the reference to JavaScript in its name, JSON is a language-independent syntax and native support for it has been included in many modern programming languages. In fact, JSON is so popular nowadays that entire database management systems have built their record structure around it, for example Apache CouchDB.
As a Web developer who does a lot of work with PL/SQL, I have recently found myself creating PL/SQL procedures that output JSON data, and making these procedures available as RESTful HTTP services that are then consumed by Ajax functions in the front-end of my applications. This can be a bit of a pain, however, as I need to output the JSON data manually, making it very prone to errors and very difficult to debug in many cases.
Thankfully, an open source library for PL/SQL called PL/JSON is available that resolves some of the issues associated with working with JSON data in an Oracle application. In this post, you will learn how to install and use PL/JSON to work with JSON data in your own PL/SQL applications.
Download and install the library
The latest version of PL/JSON, at the time of writing, is version 0.8.6. The compressed archive is less than 200KB in size. You can download PL/JSON from SourceForge at http://sourceforge.net/projects/pljson/files/. Unzip the library to your hard drive and install it in a SQL*Plus session using the following command:
@install
You should see the following output:
----------------------------------- -- Compiling objects for PL/JSON -- ----------------------------------- PL/SQL procedure successfully complete Type created. No errors. Type body created. No errors. Type created. No errors. Type body created. No errors. Type created. No errors. Type created. No errors. Type created. No errors. Type created. No errors. Type created. No errors. Type created. No errors. Package created. Package body created. Package created. Package body created. Type body created. No errors. Type body created. No errors. Package created. Package body created.
Assuming you see no errors from running the install script, PL/JSON is now installed in your Oracle database.
Using PL/JSON
With PL/JSON installed, you can now start working with the traditional “Hello, world” example, using the following PL/SQL code:
set serveroutput on
declare
jsonObj json;
begin
--Create a new JSON object, passing the JSON code as the constructor
jsonObj := json('{"greeting":"Hello World"}');
--Output the value for the JSON data with the key "greeting"
dbms_output.put_line(json_ext.get_varchar2(jsonObj, 'greeting'));
end;
/
This produces the following output:
Hello, World
As you can see from the above output, PL/JSON parses JSON data. But what if you want to create a JSON object without actually providing the data in JSON format. Take the following example:
set serveroutput on
declare
jsonObj json;
begin
--Use an empty constructor to create a blank JSON object
jsonObj := json();
-- Use the put procedure to add a string, number, boolean and null property to the JSON object
jsonObj.put('name', 'Joe Lennon');
jsonObj.put('age', 24);
jsonObj.put('awesome', json_bool(true));
jsonObj.put('children', json_null());
--Print the string representation of the JSON object (pretty-print)
jsonObj.print;
dbms_output.put_line('Am I awesome?');
--Use getters to retrieve the value of the boolean property "awesome" and print the result
dbms_output.put_line(json_ext.get_json_bool(jsonObj, 'awesome').to_char);
end;
/
The output for the above looks like:
{
"name" : "Joe Lennon",
"age" : 24,
"awesome" : true,
"children" : null
}
Am I awesome?
true
JSON Arrays
JSON objects can contain data in several types – number, string, boolean, null or array. At this point, you’ve seen how to work with the first four of these types, but not arrays. PL/JSON refers to these as a json_list. Working with json_list objects is very similar to working with a regular JSON object, as shown in the following example:
set serveroutput on
declare
jsonArray json_list;
jsonObj json;
begin
jsonArray := json_list('[{"name":"Joe","age":24},{"name":"Jill","age":26}]');
jsonObj := json.to_json(jsonArray.get_elem(1));
dbms_output.put_line(json_ext.get_varchar2(jsonObj, 'name'));
jsonObj := json.to_json(jsonArray.get_elem(2));
dbms_output.put_line(to_char(json_ext.get_number(jsonObj, 'age')));
end;
/
The above code create a JSON array (or json_list) containing two objects with two properties, name and age. The first object has the name “Joe” and age 24, the second has name “Jill” and age 26. The get_elem function is used to return an item in the JSON array, and the to_json function casts this is a JSON object. In the above example, you first assign jsonObj to the first object in the JSON array, printing out the value of the name property for this object (in this case, the string value “Joe”). Next, you assign jsonObj to the second object in the array, and print out the value of the age property (in this case, age is 26). The output for this example is as follows:
Joe 26
To wrap up this post, let’s have a look at a more complex scenario for using JSON in PL/SQL. Let’s say that you want to create a JSON representation of the result of a SQL statement. The following example demonstrates just that:
set serveroutput on
declare
jsonArray json_list;
jsonObj json;
cursor get_data is
select initcap(lower(object_type)) name, count(*) count
from all_objects
where upper(object_type) like 'INDEX%'
group by object_type;
begin
jsonArray := json_list();
for objType in get_data loop
jsonObj := json();
jsonObj.put('object_type', objType.name);
jsonObj.put('count', objType.count);
jsonArray.add_elem(jsonObj.to_anydata);
end loop;
jsonArray.print;
dbms_output.new_line;
for i in 1..jsonArray.count loop
dbms_output.put_line(
json_ext.get_varchar2(
json.to_json(jsonArray.get_elem(i)),
'object_type'
)||'->'||
to_char(json_ext.get_number(
json.to_json(jsonArray.get_elem(i)),
'count'
))
);
end loop;
end;
/
In the example above, you first initialize the JSON array to an empty json_list. Next, you loop through the get_data cursor, which selects back the counts for all object types in the database that begin with “INDEX”. For each iteration of this loop, a JSON object is created, the object type name and count are added as properties to the object, and the object is added to the JSON array. Then the string representation of the array is printed as output. Next, you loop through the JSON array itself, and print out the object_type and count properties for each item in the list. The overall output should look as follows:
[{
"object_type" : "Index Partition",
"count" : 99
}, {
"object_type": "Index",
"count" : 1411
}, {
"object_type" : "Indextype",
"count" : 8
}]
Index Partition->99
Index->1411
Indextype->8
It’s important to note that the “print” function which outputs a string representation of JSON objects or arrays merely uses the DBMS_OUTPUT.PUT_LINE Oracle function to dump data to the SQL prompt. There are buffer limitations with this function, particularly on clients before 10g Release 2 (10.2). As a result, on large sets of data you may get an error:
ORA-06502: PL/SQL: numeric or value error: host bind array too small
This is not an issue with PL/JSON, but rather an issue with the Oracle DBMS_OUTPUT.PUT_LINE function. Your JSON objects can be used in other means perfectly fine, but the print member function for the json and json_list objects suffer from this limitation.
PL/JSON provides a ton of excellent features for working with JSON in PL/SQL. The best way to grips with it is to get your hands dirty and try it out for yourself. This post should be a good base to start from, and you can find out more by reading the doc.pdf file that comes with PL/JSON. Also, be sure to check out the examples folder, as it contains some good sample usages that are ready for you to test out. Finally, check the source code itself, particularly the type specification files:
- json.typ
- json_list.typ
As these will give you a good idea of the member functions available for json and json_list objects. If you have any specific questions about PL/JSON, leave a comment and I will do my best to answer them.
