MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘Oracle’ Category

Oracle Cleanup a Schema

with one comment

Back in January 2014, I wrote a script to cleanup an Oracle student schema. It worked well until I started using APEX 4 in my student schema. You create the following 75 objects when you create an APEX 4 schema.

OBJECT TYPE    TOTAL
------------ -------
TABLE		  17
INDEX		  28
SEQUENCE	   5
TRIGGER 	  14
LOB		   9
FUNCTION	   2

Here’s the modified script that ignores the objects created automatically by Oracle APEX when you create a student workspace:

BEGIN
  FOR i IN (SELECT    object_name
            ,         object_type
            ,         last_ddl_time
            FROM      user_objects
            WHERE     object_name NOT IN
                       ('APEX$_WS_WEBPG_SECTION_HISTORY','APEX$_WS_WEBPG_SECTIONS_T1'
                       ,'APEX$_WS_WEBPG_SECTIONS_PK','APEX$_WS_WEBPG_SECTIONS'
                       ,'APEX$_WS_WEBPG_SECHIST_IDX1','APEX$_WS_TAGS_T1'
                       ,'APEX$_WS_TAGS_PK','APEX$_WS_TAGS_IDX2','APEX$_WS_TAGS_IDX1'
                       ,'APEX$_WS_TAGS','APEX$_WS_ROWS_T1','APEX$_WS_ROWS_PK'
                       ,'APEX$_WS_ROWS_IDX','APEX$_WS_ROWS','APEX$_WS_NOTES_T1'
                       ,'APEX$_WS_NOTES_PK','APEX$_WS_NOTES_IDX2','APEX$_WS_NOTES_IDX1'
                       ,'APEX$_WS_NOTES','APEX$_WS_LINKS_T1','APEX$_WS_LINKS_PK'
                       ,'APEX$_WS_LINKS_IDX2','APEX$_WS_LINKS_IDX1','APEX$_WS_LINKS'
                       ,'APEX$_WS_HISTORY_IDX','APEX$_WS_HISTORY','APEX$_WS_FILES_T1'
                       ,'APEX$_WS_FILES_PK','APEX$_WS_FILES_IDX2','APEX$_WS_FILES_IDX1'
                       ,'APEX$_WS_FILES','APEX$_ACL_T1','APEX$_ACL_PK','APEX$_ACL_IDX1'
                       ,'APEX$_ACL','CUSTOM_AUTH','CUSTOM_HASH','DEPT','EMP'
                       ,'UPDATE_ORDER_TOTAL')
            AND NOT ((object_name LIKE 'DEMO%' OR
                      object_name LIKE 'INSERT_DEMO%' OR
                      object_name LIKE 'BI_DEMO%') AND
                      object_type IN ('TABLE','INDEX','SEQUENCE','TRIGGER'))
            AND NOT (object_name LIKE 'SYS_LOB%' AND object_type = 'LOB')
            AND NOT (object_name LIKE 'SYS_C%' AND object_type = 'INDEX')
            ORDER BY object_type DESC) LOOP
 
    /* Drop types in descending order. */
    IF i.object_type = 'TYPE' THEN
 
      /* Drop type and force operation because dependencies may exist. Oracle 12c
         also fails to remove object types with dependents in pluggable databases
         (at least in release 12.1). Type evolution works in container database
         schemas. */
      EXECUTE IMMEDIATE 'DROP '||i.object_type||' '||i.object_name||' FORCE';
 
    /* Drop table tables in descending order. */
    ELSIF i.object_type = 'TABLE' THEN
 
      /* Drop table with cascading constraints to ensure foreign key constraints
         don't prevent the action. */
      EXECUTE IMMEDIATE 'DROP '||i.object_type||' '||i.object_name||' CASCADE CONSTRAINTS PURGE';
 
      /* Oracle 12c ONLY: Purge the recyclebin to dispose of system-generated
         sequence values because dropping the table doesn't automatically 
         remove them from the active session.
         CRITICAL: Remark out the following when working in Oracle Database 11g. */
      EXECUTE IMMEDIATE 'PURGE RECYCLEBIN';
 
    ELSIF i.object_type = 'LOB' OR i.object_type = 'INDEX' THEN
 
      /* A system generated LOB column or INDEX will cause a failure in a
         generic drop of a table because it is listed in the cursor but removed
         by the drop of its table. This NULL block ensures there is no attempt
         to drop an implicit LOB data type or index because the dropping the
         table takes care of it. */
      NULL;
 
    ELSE
 
      dbms_output.put_line('DROP '||i.object_type||' '||i.object_name||';');
      /* Drop any other objects, like sequences, functions, procedures, and packages. */
      EXECUTE IMMEDIATE 'DROP '||i.object_type||' '||i.object_name;
 
    END IF;
  END LOOP;
END;
/

As always, I hope this helps others.

Written by maclochlainn

April 19th, 2015 at 7:13 pm

Install Ruby on Fedora

with 4 comments

I use a Fedora 20 VM image to teach Oracle and MySQL technology. Last week, I expanded the Fedora VM image to support a full LAMP stack. This blog shows you how to install Ruby on Fedora and successfully generate the Rails gems.

Connect as the root user and use yum to install the libraries. My approach is by library or small groups. Naturally, you start with the ruby library.

yum install ruby

You will see the following:

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                                  |  14 kB  00:00     
updates                                                     | 4.9 kB  00:00     
(1/3): mysql56-community/20/x86_64/primary_db               |  80 kB  00:00     
(2/3): pgdg93/20/x86_64/primary_db                          |  80 kB  00:00     
(3/3): updates/20/x86_64/primary_db                         |  13 MB  00:06     
(1/2): updates/20/x86_64/pkgtags                            | 1.4 MB  00:01     
(2/2): updates/20/x86_64/updateinfo                         | 1.9 MB  00:01     
Resolving Dependencies
--> Running transaction check
---> Package ruby.x86_64 0:2.0.0.353-16.fc20 will be installed
--> Processing Dependency: ruby-libs(x86-64) = 2.0.0.353-16.fc20 for package: ruby-2.0.0.353-16.fc20.x86_64
--> Processing Dependency: rubygem(bigdecimal) >= 1.2.0 for package: ruby-2.0.0.353-16.fc20.x86_64
--> Processing Dependency: ruby(rubygems) >= 2.0.3 for package: ruby-2.0.0.353-16.fc20.x86_64
--> Processing Dependency: /usr/bin/ruby for package: ruby-2.0.0.353-16.fc20.x86_64
--> Processing Dependency: libruby.so.2.0()(64bit) for package: ruby-2.0.0.353-16.fc20.x86_64
--> Running transaction check
---> Package ruby-libs.x86_64 0:2.0.0.353-16.fc20 will be installed
---> Package rubygem-bigdecimal.x86_64 0:1.2.0-16.fc20 will be installed
---> Package rubygems.noarch 0:2.1.11-115.fc20 will be installed
--> Processing Dependency: rubygem(rdoc) >= 4.0.0 for package: rubygems-2.1.11-115.fc20.noarch
--> Processing Dependency: rubygem(psych) >= 2.0.0 for package: rubygems-2.1.11-115.fc20.noarch
--> Processing Dependency: rubygem(io-console) >= 0.4.1 for package: rubygems-2.1.11-115.fc20.noarch
---> Package rubypick.noarch 0:1.1.1-1.fc20 will be installed
--> Running transaction check
---> Package rubygem-io-console.x86_64 0:0.4.2-16.fc20 will be installed
---> Package rubygem-psych.x86_64 0:2.0.0-16.fc20 will be installed
--> Processing Dependency: libyaml-0.so.2()(64bit) for package: rubygem-psych-2.0.0-16.fc20.x86_64
---> Package rubygem-rdoc.noarch 0:4.0.1-2.fc20 will be installed
--> Processing Dependency: rubygem(json) < 2 for package: rubygem-rdoc-4.0.1-2.fc20.noarch
--> Processing Dependency: rubygem(json) >= 1.4 for package: rubygem-rdoc-4.0.1-2.fc20.noarch
--> Processing Dependency: ruby(irb) for package: rubygem-rdoc-4.0.1-2.fc20.noarch
--> Running transaction check
---> Package libyaml.x86_64 0:0.1.6-2.fc20 will be installed
---> Package ruby-irb.noarch 0:2.0.0.353-16.fc20 will be installed
---> Package rubygem-json.x86_64 0:1.7.7-101.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                 Arch        Version                 Repository    Size
================================================================================
Installing:
 ruby                    x86_64      2.0.0.353-16.fc20       updates       65 k
Installing for dependencies:
 libyaml                 x86_64      0.1.6-2.fc20            updates       55 k
 ruby-irb                noarch      2.0.0.353-16.fc20       updates       86 k
 ruby-libs               x86_64      2.0.0.353-16.fc20       updates      2.8 M
 rubygem-bigdecimal      x86_64      1.2.0-16.fc20           updates       77 k
 rubygem-io-console      x86_64      0.4.2-16.fc20           updates       48 k
 rubygem-json            x86_64      1.7.7-101.fc20          fedora        60 k
 rubygem-psych           x86_64      2.0.0-16.fc20           updates       75 k
 rubygem-rdoc            noarch      4.0.1-2.fc20            fedora       288 k
 rubygems                noarch      2.1.11-115.fc20         updates      224 k
 rubypick                noarch      1.1.1-1.fc20            updates      6.3 k
 
Transaction Summary
================================================================================
Install  1 Package (+10 Dependent packages)
 
Total download size: 3.7 M
Installed size: 13 M
Is this ok [y/d/N]: y
Downloading packages:
(1/11): ruby-2.0.0.353-16.fc20.x86_64.rpm                   |  65 kB  00:00     
(2/11): libyaml-0.1.6-2.fc20.x86_64.rpm                     |  55 kB  00:00     
(3/11): ruby-irb-2.0.0.353-16.fc20.noarch.rpm               |  86 kB  00:00     
(4/11): rubygem-io-console-0.4.2-16.fc20.x86_64.rpm         |  48 kB  00:00     
(5/11): rubygem-json-1.7.7-101.fc20.x86_64.rpm              |  60 kB  00:00     
(6/11): rubygem-psych-2.0.0-16.fc20.x86_64.rpm              |  75 kB  00:00     
(7/11): rubypick-1.1.1-1.fc20.noarch.rpm                    | 6.3 kB  00:00     
(8/11): rubygem-bigdecimal-1.2.0-16.fc20.x86_64.rpm         |  77 kB  00:01     
(9/11): rubygem-rdoc-4.0.1-2.fc20.noarch.rpm                | 288 kB  00:00     
(10/11): ruby-libs-2.0.0.353-16.fc20.x86_64.rpm             | 2.8 MB  00:01     
(11/11): rubygems-2.1.11-115.fc20.noarch.rpm                | 224 kB  00:01     
--------------------------------------------------------------------------------
Total                                              1.4 MB/s | 3.7 MB  00:02     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : ruby-libs-2.0.0.353-16.fc20.x86_64                          1/11 
  Installing : libyaml-0.1.6-2.fc20.x86_64                                 2/11 
  Installing : rubygem-bigdecimal-1.2.0-16.fc20.x86_64                     3/11 
  Installing : rubygem-json-1.7.7-101.fc20.x86_64                          4/11 
  Installing : rubygem-psych-2.0.0-16.fc20.x86_64                          5/11 
  Installing : rubygem-rdoc-4.0.1-2.fc20.noarch                            6/11 
  Installing : ruby-irb-2.0.0.353-16.fc20.noarch                           7/11 
  Installing : rubypick-1.1.1-1.fc20.noarch                                8/11 
  Installing : ruby-2.0.0.353-16.fc20.x86_64                               9/11 
  Installing : rubygems-2.1.11-115.fc20.noarch                            10/11 
  Installing : rubygem-io-console-0.4.2-16.fc20.x86_64                    11/11 
  Verifying  : rubygem-io-console-0.4.2-16.fc20.x86_64                     1/11 
  Verifying  : rubygem-rdoc-4.0.1-2.fc20.noarch                            2/11 
  Verifying  : rubygems-2.1.11-115.fc20.noarch                             3/11 
  Verifying  : rubygem-bigdecimal-1.2.0-16.fc20.x86_64                     4/11 
  Verifying  : ruby-libs-2.0.0.353-16.fc20.x86_64                          5/11 
  Verifying  : rubygem-json-1.7.7-101.fc20.x86_64                          6/11 
  Verifying  : rubygem-psych-2.0.0-16.fc20.x86_64                          7/11 
  Verifying  : rubypick-1.1.1-1.fc20.noarch                                8/11 
  Verifying  : ruby-2.0.0.353-16.fc20.x86_64                               9/11 
  Verifying  : libyaml-0.1.6-2.fc20.x86_64                                10/11 
  Verifying  : ruby-irb-2.0.0.353-16.fc20.noarch                          11/11 
 
Installed:
  ruby.x86_64 0:2.0.0.353-16.fc20                                               
 
Dependency Installed:
  libyaml.x86_64 0:0.1.6-2.fc20                                                 
  ruby-irb.noarch 0:2.0.0.353-16.fc20                                           
  ruby-libs.x86_64 0:2.0.0.353-16.fc20                                          
  rubygem-bigdecimal.x86_64 0:1.2.0-16.fc20                                     
  rubygem-io-console.x86_64 0:0.4.2-16.fc20                                     
  rubygem-json.x86_64 0:1.7.7-101.fc20                                          
  rubygem-psych.x86_64 0:2.0.0-16.fc20                                          
  rubygem-rdoc.noarch 0:4.0.1-2.fc20                                            
  rubygems.noarch 0:2.1.11-115.fc20                                             
  rubypick.noarch 0:1.1.1-1.fc20                                                
 
Complete!

After you install ruby, you need to install the MySQL and Ruby development libraries, like this:

yum -y install gcc mysql-devel ruby-devel rubygems
Loaded plugins: langpacks, refresh-packagekit
Package gcc-4.8.3-7.fc20.x86_64 already installed and latest version
Package rubygems-2.1.11-115.fc20.noarch already installed and latest version
Resolving Dependencies
--> Running transaction check
---> Package mysql-community-devel.x86_64 0:5.6.24-1.fc20 will be installed
--> Processing Dependency: mysql-community-libs(x86-64) = 5.6.24-1.fc20 for package: mysql-community-devel-5.6.24-1.fc20.x86_64
---> Package ruby-devel.x86_64 0:2.0.0.353-16.fc20 will be installed
--> Running transaction check
---> Package mysql-community-libs.x86_64 0:5.6.23-1.fc20 will be updated
--> Processing Dependency: mysql-community-libs(x86-64) = 5.6.23-1.fc20 for package: mysql-community-client-5.6.23-1.fc20.x86_64
---> Package mysql-community-libs.x86_64 0:5.6.24-1.fc20 will be an update
--> Processing Dependency: mysql-community-common(x86-64) = 5.6.24-1.fc20 for package: mysql-community-libs-5.6.24-1.fc20.x86_64
--> Running transaction check
---> Package mysql-community-client.x86_64 0:5.6.23-1.fc20 will be updated
--> Processing Dependency: mysql-community-client(x86-64) = 5.6.23-1.fc20 for package: mysql-community-server-5.6.23-1.fc20.x86_64
---> Package mysql-community-client.x86_64 0:5.6.24-1.fc20 will be an update
---> Package mysql-community-common.x86_64 0:5.6.23-1.fc20 will be updated
---> Package mysql-community-common.x86_64 0:5.6.24-1.fc20 will be an update
--> Running transaction check
---> Package mysql-community-server.x86_64 0:5.6.23-1.fc20 will be updated
---> Package mysql-community-server.x86_64 0:5.6.24-1.fc20 will be an update
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                 Arch    Version               Repository          Size
================================================================================
Installing:
 mysql-community-devel   x86_64  5.6.24-1.fc20         mysql56-community  3.4 M
 ruby-devel              x86_64  2.0.0.353-16.fc20     updates            125 k
Updating for dependencies:
 mysql-community-client  x86_64  5.6.24-1.fc20         mysql56-community   19 M
 mysql-community-common  x86_64  5.6.24-1.fc20         mysql56-community  258 k
 mysql-community-libs    x86_64  5.6.24-1.fc20         mysql56-community  2.0 M
 mysql-community-server  x86_64  5.6.24-1.fc20         mysql56-community   55 M
 
Transaction Summary
================================================================================
Install  2 Packages
Upgrade             ( 4 Dependent packages)
 
Total download size: 80 M
Downloading packages:
No Presto metadata available for mysql56-community
(1/6): mysql-community-common-5.6.24-1.fc20.x86_64.rpm      | 258 kB  00:01     
(2/6): mysql-community-devel-5.6.24-1.fc20.x86_64.rpm       | 3.4 MB  00:01     
(3/6): mysql-community-libs-5.6.24-1.fc20.x86_64.rpm        | 2.0 MB  00:00     
(4/6): ruby-devel-2.0.0.353-16.fc20.x86_64.rpm              | 125 kB  00:00     
(5/6): mysql-community-client-5.6.24-1.fc20.x86_64.rpm      |  19 MB  00:09     
(6/6): mysql-community-server-5.6.24-1.fc20.x86_64.rpm      |  55 MB  00:21     
--------------------------------------------------------------------------------
Total                                              3.3 MB/s |  80 MB  00:24     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Updating   : mysql-community-common-5.6.24-1.fc20.x86_64                 1/10 
  Updating   : mysql-community-libs-5.6.24-1.fc20.x86_64                   2/10 
  Updating   : mysql-community-client-5.6.24-1.fc20.x86_64                 3/10 
  Updating   : mysql-community-server-5.6.24-1.fc20.x86_64                 4/10 
  Installing : mysql-community-devel-5.6.24-1.fc20.x86_64                  5/10 
  Installing : ruby-devel-2.0.0.353-16.fc20.x86_64                         6/10 
  Cleanup    : mysql-community-server-5.6.23-1.fc20.x86_64                 7/10 
  Cleanup    : mysql-community-client-5.6.23-1.fc20.x86_64                 8/10 
  Cleanup    : mysql-community-libs-5.6.23-1.fc20.x86_64                   9/10 
  Cleanup    : mysql-community-common-5.6.23-1.fc20.x86_64                10/10 
  Verifying  : mysql-community-client-5.6.24-1.fc20.x86_64                 1/10 
  Verifying  : mysql-community-devel-5.6.24-1.fc20.x86_64                  2/10 
  Verifying  : ruby-devel-2.0.0.353-16.fc20.x86_64                         3/10 
  Verifying  : mysql-community-libs-5.6.24-1.fc20.x86_64                   4/10 
  Verifying  : mysql-community-common-5.6.24-1.fc20.x86_64                 5/10 
  Verifying  : mysql-community-server-5.6.24-1.fc20.x86_64                 6/10 
  Verifying  : mysql-community-client-5.6.23-1.fc20.x86_64                 7/10 
  Verifying  : mysql-community-server-5.6.23-1.fc20.x86_64                 8/10 
  Verifying  : mysql-community-libs-5.6.23-1.fc20.x86_64                   9/10 
  Verifying  : mysql-community-common-5.6.23-1.fc20.x86_64                10/10 
 
Installed:
  mysql-community-devel.x86_64 0:5.6.24-1.fc20                                  
  ruby-devel.x86_64 0:2.0.0.353-16.fc20                                         
 
Dependency Updated:
  mysql-community-client.x86_64 0:5.6.24-1.fc20                                 
  mysql-community-common.x86_64 0:5.6.24-1.fc20                                 
  mysql-community-libs.x86_64 0:5.6.24-1.fc20                                   
  mysql-community-server.x86_64 0:5.6.24-1.fc20                                 
 
Complete!

After installing ruby, exit the root account to your management account and run the following command from the Linux shell:

ruby -v

It should show you:

ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]

Before you can run gem to install rails, you must install another the libxml2-devel library. Here’s the syntax to install the libxml2-devel library:

yum install libxml2-devel

You should see the following, which includes typing a y to continue:

Loaded plugins: langpacks, refresh-packagekit
Resolving Dependencies
--> Running transaction check
---> Package libxml2-devel.x86_64 0:2.9.1-3.fc20 will be installed
--> Processing Dependency: zlib-devel for package: libxml2-devel-2.9.1-3.fc20.x86_64
--> Processing Dependency: xz-devel for package: libxml2-devel-2.9.1-3.fc20.x86_64
--> Running transaction check
---> Package xz-devel.x86_64 0:5.1.2-12alpha.fc20 will be installed
---> Package zlib-devel.x86_64 0:1.2.8-3.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package             Arch         Version                   Repository     Size
================================================================================
Installing:
 libxml2-devel       x86_64       2.9.1-3.fc20              updates       1.0 M
Installing for dependencies:
 xz-devel            x86_64       5.1.2-12alpha.fc20        updates        45 k
 zlib-devel          x86_64       1.2.8-3.fc20              fedora         50 k
 
Transaction Summary
================================================================================
Install  1 Package (+2 Dependent packages)
 
Total download size: 1.1 M
Installed size: 9.1 M
Is this ok [y/d/N]: y
Downloading packages:
(1/3): xz-devel-5.1.2-12alpha.fc20.x86_64.rpm               |  45 kB  00:00     
(2/3): zlib-devel-1.2.8-3.fc20.x86_64.rpm                   |  50 kB  00:00     
(3/3): libxml2-devel-2.9.1-3.fc20.x86_64.rpm                | 1.0 MB  00:04     
--------------------------------------------------------------------------------
Total                                              264 kB/s | 1.1 MB  00:04     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : zlib-devel-1.2.8-3.fc20.x86_64                               1/3 
  Installing : xz-devel-5.1.2-12alpha.fc20.x86_64                           2/3 
  Installing : libxml2-devel-2.9.1-3.fc20.x86_64                            3/3 
  Verifying  : xz-devel-5.1.2-12alpha.fc20.x86_64                           1/3 
  Verifying  : libxml2-devel-2.9.1-3.fc20.x86_64                            2/3 
  Verifying  : zlib-devel-1.2.8-3.fc20.x86_64                               3/3 
 
Installed:
  libxml2-devel.x86_64 0:2.9.1-3.fc20                                           
 
Dependency Installed:
  xz-devel.x86_64 0:5.1.2-12alpha.fc20     zlib-devel.x86_64 0:1.2.8-3.fc20    
 
Complete!
yum install libxslt-devel

You should see the following and will need to reply with a y during install:

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                                  |  14 kB  00:00     
updates                                                     | 4.9 kB  00:00     
updates/20/x86_64/primary_db                                |  13 MB  00:07     
updates/20/x86_64/pkgtags      FAILED                                           
http://mirror.utexas.edu/fedora/linux/updates/20/x86_64/repodata/fe40e35e0289ae1470dbe8030c09b8046924cbaa5e16ac61e9411ac57477820b-pkgtags.sqlite.gz: [Errno 14] HTTP Error 404 - Not Found
Trying other mirror.
(1/2): updates/20/x86_64/updateinfo                         | 1.9 MB  00:02     
(2/2): updates/20/x86_64/pkgtags                            | 1.4 MB  00:00     
Resolving Dependencies
--> Running transaction check
---> Package libxslt-devel.x86_64 0:1.1.28-5.fc20 will be installed
--> Processing Dependency: libgcrypt-devel for package: libxslt-devel-1.1.28-5.fc20.x86_64
--> Running transaction check
---> Package libgcrypt-devel.x86_64 0:1.5.3-2.fc20 will be installed
--> Processing Dependency: libgpg-error-devel for package: libgcrypt-devel-1.5.3-2.fc20.x86_64
--> Running transaction check
---> Package libgpg-error-devel.x86_64 0:1.12-1.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                  Arch         Version               Repository    Size
================================================================================
Installing:
 libxslt-devel            x86_64       1.1.28-5.fc20         fedora       309 k
Installing for dependencies:
 libgcrypt-devel          x86_64       1.5.3-2.fc20          fedora       127 k
 libgpg-error-devel       x86_64       1.12-1.fc20           fedora        16 k
 
Transaction Summary
================================================================================
Install  1 Package (+2 Dependent packages)
 
Total download size: 451 k
Installed size: 2.6 M
Is this ok [y/d/N]: y
Downloading packages:
(1/3): libgcrypt-devel-1.5.3-2.fc20.x86_64.rpm              | 127 kB  00:00     
(2/3): libgpg-error-devel-1.12-1.fc20.x86_64.rpm            |  16 kB  00:00     
(3/3): libxslt-devel-1.1.28-5.fc20.x86_64.rpm               | 309 kB  00:00     
--------------------------------------------------------------------------------
Total                                              454 kB/s | 451 kB  00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : libgpg-error-devel-1.12-1.fc20.x86_64                        1/3 
  Installing : libgcrypt-devel-1.5.3-2.fc20.x86_64                          2/3 
  Installing : libxslt-devel-1.1.28-5.fc20.x86_64                           3/3 
  Verifying  : libgcrypt-devel-1.5.3-2.fc20.x86_64                          1/3 
  Verifying  : libgpg-error-devel-1.12-1.fc20.x86_64                        2/3 
  Verifying  : libxslt-devel-1.1.28-5.fc20.x86_64                           3/3 
 
Installed:
  libxslt-devel.x86_64 0:1.1.28-5.fc20                                          
 
Dependency Installed:
  libgcrypt-devel.x86_64 0:1.5.3-2.fc20 libgpg-error-devel.x86_64 0:1.12-1.fc20
 
Complete!

One more to go. You can’t run the Ruby gem utility to create the nokogiri Ruby Gem on Fedora because of a library mismatch. If you attempt to create the Rails framework, like this:

gem install rails

It’ll raise the following error message on trying to dynamically link the nokogiri Ruby Gem. The error will be something like this, and unfortunately, the log files won’t be too useful:

Running patch with /usr/local/share/gems/gems/nokogiri-1.6.6.2/ports/patches/libxml2/0001-Revert-Missing-initialization-for-the-catalog-module.patch...
Running 'patch' for libxml2 2.9.2... ERROR, review '/usr/local/share/gems/gems/nokogiri-1.6.6.2/ext/nokogiri/tmp/x86_64-redhat-linux-gnu/ports/libxml2/2.9.2/patch.log' to see what happened.
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

The error message isn’t very helpful but the fix is fortunately easy. You install the nokogiri Ruby Gem directly with the yum utility. The following instructs yum to proceed without waiting for you to type a y to install.

yum install -y rubygem-nokogiri
Loaded plugins: langpacks, refresh-packagekit
Resolving Dependencies
--> Running transaction check
---> Package rubygem-nokogiri.x86_64 0:1.6.6.2-1.fc20 will be installed
--> Finished Dependency Resolution
 
Dependencies Resolved
 
================================================================================
 Package                Arch         Version                Repository     Size
================================================================================
Installing:
 rubygem-nokogiri       x86_64       1.6.6.2-1.fc20         updates       534 k
 
Transaction Summary
================================================================================
Install  1 Package
 
Total download size: 534 k
Installed size: 834 k
Downloading packages:
rubygem-nokogiri-1.6.6.2-1.fc20.x86_64.rpm                  | 534 kB  00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction (shutdown inhibited)
  Installing : rubygem-nokogiri-1.6.6.2-1.fc20.x86_64                       1/1 
  Verifying  : rubygem-nokogiri-1.6.6.2-1.fc20.x86_64                       1/1 
 
Installed:
  rubygem-nokogiri.x86_64 0:1.6.6.2-1.fc20                                      
 
Complete!

Now you can use the Ruby gem utility to create the Rails framework like this:

gem install rails

This will take a couple minutes typically, so be patient. You see something like this, dependent on the release:

Fetching: loofah-2.0.1.gem (100%)
Successfully installed loofah-2.0.1
Fetching: rails-html-sanitizer-1.0.2.gem (100%)
Successfully installed rails-html-sanitizer-1.0.2
Fetching: rails-deprecated_sanitizer-1.0.3.gem (100%)
Successfully installed rails-deprecated_sanitizer-1.0.3
Fetching: rails-dom-testing-1.0.6.gem (100%)
Successfully installed rails-dom-testing-1.0.6
Fetching: builder-3.2.2.gem (100%)
Successfully installed builder-3.2.2
Fetching: erubis-2.7.0.gem (100%)
Successfully installed erubis-2.7.0
Fetching: actionview-4.2.1.gem (100%)
Successfully installed actionview-4.2.1
Fetching: actionpack-4.2.1.gem (100%)
Successfully installed actionpack-4.2.1
Fetching: activemodel-4.2.1.gem (100%)
Successfully installed activemodel-4.2.1
Fetching: arel-6.0.0.gem (100%)
Successfully installed arel-6.0.0
Fetching: activerecord-4.2.1.gem (100%)
Successfully installed activerecord-4.2.1
Fetching: globalid-0.3.5.gem (100%)
Successfully installed globalid-0.3.5
Fetching: activejob-4.2.1.gem (100%)
Successfully installed activejob-4.2.1
Fetching: mime-types-2.4.3.gem (100%)
Successfully installed mime-types-2.4.3
Fetching: mail-2.6.3.gem (100%)
Successfully installed mail-2.6.3
Fetching: actionmailer-4.2.1.gem (100%)
Successfully installed actionmailer-4.2.1
Fetching: rake-10.4.2.gem (100%)
Successfully installed rake-10.4.2
Fetching: thor-0.19.1.gem (100%)
Successfully installed thor-0.19.1
Fetching: railties-4.2.1.gem (100%)
Successfully installed railties-4.2.1
Fetching: bundler-1.9.2.gem (100%)
Successfully installed bundler-1.9.2
Fetching: hike-1.2.3.gem (100%)
Successfully installed hike-1.2.3
Fetching: multi_json-1.11.0.gem (100%)
Successfully installed multi_json-1.11.0
Fetching: tilt-1.4.1.gem (100%)
Successfully installed tilt-1.4.1
Fetching: sprockets-2.12.3.gem (100%)
Successfully installed sprockets-2.12.3
Fetching: sprockets-rails-2.2.4.gem (100%)
Successfully installed sprockets-rails-2.2.4
Fetching: rails-4.2.1.gem (100%)
Successfully installed rails-4.2.1
Parsing documentation for actionmailer-4.2.1
Installing ri documentation for actionmailer-4.2.1
Parsing documentation for actionpack-4.2.1
Installing ri documentation for actionpack-4.2.1
Parsing documentation for actionview-4.2.1
Installing ri documentation for actionview-4.2.1
Parsing documentation for activejob-4.2.1
Installing ri documentation for activejob-4.2.1
Parsing documentation for activemodel-4.2.1
Installing ri documentation for activemodel-4.2.1
Parsing documentation for activerecord-4.2.1
Installing ri documentation for activerecord-4.2.1
Parsing documentation for arel-6.0.0
Installing ri documentation for arel-6.0.0
Parsing documentation for builder-3.2.2
Installing ri documentation for builder-3.2.2
Parsing documentation for bundler-1.9.2
Installing ri documentation for bundler-1.9.2
Parsing documentation for erubis-2.7.0
Installing ri documentation for erubis-2.7.0
Parsing documentation for globalid-0.3.5
Installing ri documentation for globalid-0.3.5
Parsing documentation for hike-1.2.3
Installing ri documentation for hike-1.2.3
Parsing documentation for loofah-2.0.1
Installing ri documentation for loofah-2.0.1
Parsing documentation for mail-2.6.3
Installing ri documentation for mail-2.6.3
Parsing documentation for mime-types-2.4.3
Installing ri documentation for mime-types-2.4.3
Parsing documentation for multi_json-1.11.0
Installing ri documentation for multi_json-1.11.0
Parsing documentation for rails-4.2.1
Installing ri documentation for rails-4.2.1
Parsing documentation for rails-deprecated_sanitizer-1.0.3
Installing ri documentation for rails-deprecated_sanitizer-1.0.3
Parsing documentation for rails-dom-testing-1.0.6
Installing ri documentation for rails-dom-testing-1.0.6
Parsing documentation for rails-html-sanitizer-1.0.2
Installing ri documentation for rails-html-sanitizer-1.0.2
Parsing documentation for railties-4.2.1
Installing ri documentation for railties-4.2.1
Parsing documentation for rake-10.4.2
Installing ri documentation for rake-10.4.2
Parsing documentation for sprockets-2.12.3
Installing ri documentation for sprockets-2.12.3
Parsing documentation for sprockets-rails-2.2.4
Installing ri documentation for sprockets-rails-2.2.4
Parsing documentation for thor-0.19.1
Installing ri documentation for thor-0.19.1
Parsing documentation for tilt-1.4.1
Installing ri documentation for tilt-1.4.1
Done installing documentation for actionmailer, actionpack, actionview, activejob, activemodel, activerecord, arel, builder, bundler, erubis, globalid, hike, loofah, mail, mime-types, multi_json, rails, rails-deprecated_sanitizer, rails-dom-testing, rails-html-sanitizer, railties, rake, sprockets, sprockets-rails, thor, tilt after 475 seconds
26 gems installed

If you want to install Phusion Passenger, mod_passenger is already installed. You should note that support and testing for this stops at Fedora V17. You can verify installation with the following command:

yum list mod_passenger

It returns:

Loaded plugins: langpacks, refresh-packagekit
Available Packages
mod_passenger.x86_64                   4.0.53-3.fc20.2                   updates

You can also install the Ruby Gem for Passenger, like this:

gem install passenger

It should take less than 2 minutes and return something like this:

Fetching: passenger-5.0.6.gem (100%)
Building native extensions.  This could take a while...
Successfully installed passenger-5.0.6
Parsing documentation for passenger-5.0.6
Installing ri documentation for passenger-5.0.6
Done installing documentation for passenger after 9 seconds
1 gem installed

As always, I hope this was helpful. I’ll add a post with the remaining MySQL and Oracle connection details soon.

Written by maclochlainn

April 10th, 2015 at 2:28 am

APEX Create Table

with 2 comments

The following walks you through how you sign on to a STUDENT Workspace with Oracle’s APEX product. It shows you how to create a new table with the Object Browser tool.

You can find instructions on how to create your own STUDENT Workspace in this blog post. Overall, Oracle APEX is a valuable tool to learn and master.

UseStudentAPEX01

  1. You start the process by accessing the Oracle Database 11g APEX, which you can access at http://localhost:8080/apex by default on the server. If you’ve got a static IP address for your instance, you can replace localhost with the IP address or hostname for the IP address.

    • Workspace: STUDENT
    • Username:  ADMIN
    • Password:  STUDENT

UseStudentAPEX02

  1. After you login to the STUDENT workspace, you have four options. They are the: Application Builder, SQL Workshop, Team Development, and Administration. You start the process by accessing the Oracle Database 11g APEX, which you can access at http://localhost:8080/apex by default on the server. If you’ve got a static IP address for your instance, you can replace localhost with the IP address or hostname for the IP address. Click on the Object Browser icon to proceed.

UseStudentAPEX02A

  1. Clicking the SQL Workshop icon takes you to the second level menu. You click the Object Browser icon to create a database object.

OracleAPEXCT01

  1. After clicking the Object Browser icon, you see the screen at the left. Click the Create button to create a table.

OracleAPEXCT02

  1. After clicking the Create button, you see the screen at the left. Click the type of database object that you want to create. In our case, we click the Table hypertext to start the create table workflow.

OracleAPEXCT03

  1. After clicking the Table hyperlink, you see the Create Table screen at the left. Enter the column names, choose their data types and set the scale and precision. You should also check the Not Null checkbox when you want a column to be mandatory. Click the Next button to continue the create table workflow.

OracleAPEXCT04

  1. After entering the column names, you should choose the data types, enter the scale and precision, and check the NOT NULL checkbox to make appropriate columns mandatory by applying NOT NULL database constraints. If you run out of entry rows, you can click the Add Column button to add new rows. Click the Next button to continue the create table workflow when you’ve defined the columns.

OracleAPEXCT05

  1. After defining the column names, you should choose whether the primary key will use a new sequence or an existing sequence. You also have the ability to not assign a primary key value or simply leave it unpopulated when inserting new rows. The example creates an IMAGE_PK primary key constraint on the IMAGE_ID column, and declares an IMAGE_SEQ sequence value. Click the Next button to continue the create table workflow when you’ve defined the primary key constraint and any new sequence value for the primary key column.

OracleAPEXCTFK1

  1. After defining the primary key constraint, you can define foreign key column constraints. You enter a foreign key constraint name, choose between a Disallow Delete, Cascade Delete, or Set Null on Delete rule, select the foreign key column, the foreign key’s referenced table and column. Click the Add button to continue the create table workflow.

OracleAPEXCTFK2

  1. After defining a foreign key constraint, you can see the constraint that you created. Then, you can define another foreign key column constraints. You repeat the steps from the prior steps to add another foreign key constraint. Click the Add button to create a second foreign key constraint and complete the create table workflow.

OracleAPEXCTFK3

  1. After defining a second foreign key constraint, you see the following two foreign key constraints. Click the Next button to complete the create table workflow.

OracleAPEXTCUK01

  1. After defining all the foreign key constraints, you can create check and unique constraints. You check a radio button for a check or unique constraint, and then you select the columns for the constraint’s key. Click the /Add button to create any check or unique constraints as part of the create table workflow.

OracleAPEXTCUK02

  1. After defining all check and unique key constraints, you can see them in the Constraints box. Click the Next button to complete the create table workflow.

OracleAPEXCTC01

  1. After defining all items about the table, you can see the SQL to create the IMAGE table and its constraints. You can copy the SQL into a file for later use when writing a re-runnable script. Click the Create button to complete the create table workflow and create the table.

     

    The following are the contents of the script for the actions you’ve defined:

    CREATE table "IMAGE" (
        "IMAGE_ID"         NUMBER NOT NULL,
        "FILE_NAME"        VARCHAR2(60) NOT NULL,
        "MIME_TYPE"        NUMBER NOT NULL,
        "ITEM_IMAGE"       BLOB,
        "CREATED_BY"       NUMBER NOT NULL,
        "CREATION_DATE"    DATE NOT NULL,
        "LAST_UPDATED_BY"  NUMBER NOT NULL,
        "LAST_UPDATE_DATE" DATE NOT NULL,
        constraint  "IMAGE_PK" primary key ("IMAGE_ID")
    )
    /
    
    CREATE sequence "IMAGE_SEQ" 
    /
    
    CREATE trigger "BI_IMAGE"  
      before insert on "IMAGE"              
      for each row 
    begin  
      if :NEW."IMAGE_ID" is null then
        select "IMAGE_SEQ".nextval into :NEW."IMAGE_ID" from dual;
      end if;
    end;
    /   
    
    ALTER TABLE "IMAGE" ADD CONSTRAINT "IMAGE_FK1" 
    FOREIGN KEY ("CREATED_BY")
    REFERENCES "SYSTEM_USER" ("SYSTEM_USER_ID")
    
    /
    ALTER TABLE "IMAGE" ADD CONSTRAINT "IMAGE_FK2" 
    FOREIGN KEY ("LAST_UPDATED_BY")
    REFERENCES "SYSTEM_USER" ("SYSTEM_USER_ID")
    
    /
    alter table "IMAGE" add
    constraint "IMAGE_UK1" 
    unique ("FILE_NAME","MIME_TYPE")
    /   
    

OracleAPEXTable

  1. After creating the table, trigger, sequence, and constraints, you can see the table definition. You also have the ability to modify the table. At this point, you can create another structure or you can click the Home or SQL Workshop menu choice.

As always, I hope this helps those looking to learn new things and approaches.

Written by maclochlainn

April 7th, 2015 at 10:21 pm

APEX SQL Query

without comments

The following walks through how you sign on to a STUDENT Workspace with Oracle’s APEX product and write and run free-form SQL statements. You can find instructions on how to create your own STUDENT Workspace.

While this blog introduces several concepts and features of Oracle APEX, it only focuses on how to write and run free-form SQL statements. Overall, Oracle APEX is a valuable tool to learn and master.

UseStudentAPEX01

  1. You start the process by accessing the Oracle Database 11g APEX, which you can access at http://localhost:8080/apex by default on the server. If you’ve got a static IP address for your instance, you can replace localhost with the IP address or hostname for the IP address.

    • Workspace: STUDENT
    • Username:  ADMIN
    • Password:  STUDENT

UseStudentAPEX02

  1. After you login to the STUDENT workspace, you have four options. They are the: Application Builder, SQL Workshop, Team Development, and Administration. You start the process by accessing the Oracle Database 11g APEX, which you can access at http://localhost:8080/apex by default on the server. If you’ve got a static IP address for your instance, you can replace localhost with the IP address or hostname for the IP address. Click on the SQL Workshop icon to proceed.

    • Application Builder: Let’s you build custom APEX applications.
    • SQL Workshop: Let’s you work with custom SQL, and APEX provides you with the following utilities:
      • Object Browser: Lets you create tables, views, and other objects.
      • SQL Commands: Lets you run individual SQL statements inside a browser window and returns results in the bottom pane.
      • SQL Scripts: Lets you create, upload, delete, and run scripts from the browser.
      • Query Builder: Lets you create free form queries that include joins between tables, but limits you to primary to foreign key table relationships. That means you can’t write range joins with a cross join and the BETWEEN operator and you can’t write self-joins.
      • Utilities: Lets you work with the Data Workshop (imports and exports data), Object Reports (a SQL report writer tool), Generate DDL (a tool that creates structures in the database), User Interface Defaults (coordinate data dictionary), Schema Comparison (a tool to compare similarities between schemas, About Database (the ability to connect as the database administrator), and Recycle Bin (dropped and purged structures).
    • Team Development: A project management tool.
    • Administration: Lets you manage database services, users and groups, monitor activities, and dashboards. You should note that the SQL query doesn’t have a semicolon like it would in a SQL*Plus environment. The Run button acts as the execution operator and effectively replaces the role of the semicolon, which traditionally executes a statement.

UseStudentAPEX02A

  1. Clicking the SQL Workshop icon takes you to the second level menu. You click the SQL Commands icon to enter a free-form SQL statement. Click on the SQL Commands icon to proceed.

UseStudentAPEX03

  1. The first text panel lets you enter free-form queries. The Autocommit checkbox is enabled, which means the result of INSERT and UPDATE statements are immediate and don’t require a COMMIT statement. The second text panel displays results from a query or acknowledgment of statement completion.

UseStudentAPEX04

  1. This screen shot shows a query in the first panel and the results of the query in the second panel.

As always, I hope this helps those looking to learn new things and approaches.

Written by maclochlainn

April 5th, 2015 at 4:36 pm

APEX Create Workspace

with 2 comments

In a prior post, I showed you how to access Oracle Database 11g XE APEX. This post shows you how to create a basic workspace against a student database (or, what Oracle lables a schema, which is synonymous with a database).

Oracle11gAPEX_01

  1. You start the process by accessing the Oracle Database 11g APEX, which you can access at http://localhost:8080/apex by default on the server. If you’ve got a static IP address for your instance, you can replace localhost with the IP address or hostname for the IP address.

    • Workspace: INTERNAL
    • Username:  ADMIN
    • Password:  installation_system_password

Oracle11gAPEX_02

  1. After logging into the Oracle Application Express (APEX) system, you see the Home page at the left. Click the Manage Workspace button on the Home page.

Oracle11gAPEX_03

  1. Manage Workspace Dialog: After clicking the Manage Workspace button on the Home page, you see four major options to manage workspaces. They are the Workspace Actions, Workspace Reports, Export Import, and Manage Applications. You want to click on the Create Workspace to create a new workspace.

Oracle11gAPEX_03A

  1. Identify Workspace Diaglog: Enter a Workspace Name and Workspace Description. Then, click on the Next button move forward in the workflow.

Oracle11gAPEX_04

  1. Create Workspace Dialog: You create a workspace, APEX presumes you want to create a new schema. That’s why the Re-use existing schema drop down chooses No by default. You enter the Schema Name as STUDENT, the Password for the STUDENT schema, and an initial Space Quota (MB) of 100. Then, click the Next button to continue.

Oracle11gAPEX_05

  1. Identify Schema Dialog: If the schema you chose exists, you get the correction dialog. You need to change the Re-use existing schema drop down from No to Yes. Then, click the Next button to continue.

Oracle11gAPEX_06

  1. Identify Administrator Dialog: Here you enter an Administrator Username, Password, First Name, Last Name, and email address. Then, click the Next button to continue.

Oracle11gAPEX_07

  1. Confirm Request Dialog: Here you review your entries and click the Confirm Request button to continue.

Oracle11gAPEX_08

  1. Success Confirmation Dialog: Here you click the Done Request button to continue.

As always, I hope this helps you learn how to create a workspace.

Written by maclochlainn

April 5th, 2015 at 1:38 am

Oracle 11g XE APEX

with 3 comments

The question for most new Oracle users is what’s Apex? They have a different question When they discover how to connect to the Oracle Database 11g XE default instance with this URL:

http://localhost:8080/apex

You’ll see the following web site, and wonder what do I enter for the Workspace, the Username, and the Password values?

Apex01

The answers are:

  • Default Workspace: INTERNAL
  • Default User: ADMIN
  • Default Password: SYS or SYSTEM Password from Install

Enter those values within the initial password time interval and you’ll arrive at the next screen where you can manage the Oracle Database 11g XE instance. If you wait too long, you’ll be redirected to enter the original SYS or SYSTEM password from install and a new password twice. The rules for a new password are:

  • Password must contain at least 6 characters.
  • New password must differ from old password by at least 2 characters.
  • Password must contain at least one numeric character (0123456789).
  • Password must contain at least one punctuation character (!”#$%&()“*+,-/:;<=>?_).
  • Password must contain at least one upper-case alphabetic character.
  • Password must not contain username.

Whether you go directly to the next screen or have to enter your a new password, you should see the following screen:

Apex02

You can find the default configuration for the installation with the following anonymous PL/SQL block:

DECLARE
  /* Declare variables. */
  lv_endpoint    NUMBER := 1;
  lv_host        VARCHAR2(80);
  lv_port        NUMBER;
  lv_protocol    NUMBER;
BEGIN
  /* Check for current XDB settings. */
  dbms_xdb.getlistenerendpoint( lv_endpoint
                              , lv_host
                              , lv_port
                              , lv_protocol );
 
  /* Print the values. */
  dbms_output.put_line('Endpoint: ['||lv_endpoint||']'||CHR(10)||
                       'Host:     ['||lv_host||']'||CHR(10)||
                       'Port:     ['||lv_port||']'||CHR(10)||
                       'Protocol: ['||lv_protocol||']');
END;
/

It should print the following:

Endpoint: [1]
Host:	  [localhost]
Port:	  [8080]
Protocol: [1]

This is a standalone configuration and you can’t connect to the XDB server from another machine. You can only connect from the local machine.

I hope this helps those trying to use the default Apex 4 installation provided as part of the Oracle Database 11g XE instance. You can read an older post of mine that shows you how to set up a basic Workspace, but after reflection I’ll write more about creating and managing workspaces.

Written by maclochlainn

April 2nd, 2015 at 1:18 am

Functions disallow NDS

with 2 comments

My students asked if you could embed an OFFSET x ROWS FETCH NEXT y ROWS ONLY clause in a SQL Server T-SQL user-defined function. The answer is no, it isn’t Oracle (yes, you can do that in Oracle Database 12c with an NDS statement). There’s an example in Chapter 2 of my Oracle Database 12c PL/SQL Programming book if you’re interested. I also demonstrate a different approach to SQL Server T-SQL table functions in this older post. However, an attempt to add the clause to a SQL Server T-SQL function, like this:

CREATE FUNCTION studentdb.getBatch
(@rows   AS INT
,@offset AS INT) RETURNS @output TABLE
( marvel_id    INT 
, avenger_name VARCHAR(30)
, first_name   VARCHAR(20)
, last_name    VARCHAR(20)) AS
BEGIN
  /* Insert the results into the table variable. */
  INSERT @output
  SELECT marvel_id
  ,      avenger_name
  ,      first_name
	,      last_name
  FROM   studentdb.marvel
  OFFSET (@offset - 1) ROWS FETCH NEXT @rows ROWS ONLY;
 
  /* Return the table variable from the function. */  
  RETURN;
END;

Throws the following errors trying to compile the function:

Msg 102, Level 15, State 1, Procedure getBatch, Line 16
Incorrect syntax near '@offset'.
Msg 153, Level 15, State 2, Procedure getBatch, Line 16
Invalid usage of the option NEXT in the FETCH statement.

If you have a strong background in Oracle and can sort through the dynamic SQL syntax for T-SQL, you might try re-writing the function to use the EXEC SP_EXECUTESQL @var; command. That rewrite that attempts to use NDS (Native Dynamic SQL) would look like this:

CREATE FUNCTION studentdb.getBatch
(@rows   AS INT
,@offset AS INT) RETURNS @output TABLE
( marvel_id    INT 
, avenger_name VARCHAR(30)
, first_name   VARCHAR(20)
, last_name    VARCHAR(20)) AS
BEGIN
  DECLARE
    /* Declare a variable for a dynamic SQL statement. */
    @stmt          VARCHAR(400);
 
    /* Assign the SQL statement to a variable. */
    SET @stmt = N'SELECT marvel_id ' +
                N',      avenger_name ' +
                N',      first_name ' +
                N',      last_name ' +
                N'FROM   studentdb.marvel ' +
                N'OFFSET ' + (@offset - 1) + N' ' +
                N'ROWS FETCH NEXT ' + @rows + N' ROWS ONLY;';
  BEGIN
    /* Insert the results into the table variable. */
    INSERT @output
    EXEC sp_executesql @stmt; 
  END;
 
  /* Return the table variable from the function. */  
  RETURN;
END;

Throws the following exception because you can’t use dynamic dispatch inside a T-SQL function:

Msg 443, Level 16, State 14, Procedure getBatch, Line 23
Invalid use of a side-effecting operator 'INSERT EXEC' within a function.

On the other hand you can rewrite the statement with a BETWEEN operator and it works somewhat like an OFFSET and FETCH operation. That refactored function would be written as follows:

CREATE FUNCTION studentdb.getBatch
(@rowa  AS INT
,@rowb AS INT) RETURNS @output TABLE
( marvel_id    INT 
, avenger_name VARCHAR(30)
, first_name   VARCHAR(20)
, last_name    VARCHAR(20)) AS
BEGIN
  /* Insert the results into the table variable. */
  INSERT @output
  SELECT marvel_id
  ,      avenger_name
  ,      first_name
  ,      last_name
  FROM   studentdb.marvel
  WHERE  marvel_id BETWEEN @rowa AND @rowb;
 
  /* Return the table variable from the function. */  
  RETURN;
END;

It doesn’t raise an exception. You can call the table function like this:

SELECT * FROM getBatch(2,3);

It returns the two rows for Iron Man and Black Widow. As always, I hope this helps.

If you want to create the test case, here’s the script you need:

SELECT 'Conditionally drop studentdb.marvel table.' AS "Statement";
IF OBJECT_ID('studentdb.marvel','U') IS NOT NULL
  DROP TABLE studentdb.marvel;
 
SELECT 'Create studentdb.marvel table.' AS "Statement";
CREATE TABLE studentdb.marvel
( marvel_id     INT          NOT NULL IDENTITY(1,1) CONSTRAINT marvel_pk PRIMARY KEY
, avenger_name  VARCHAR(30)  NOT NULL
, first_name    VARCHAR(20)  NOT NULL
, last_name     VARCHAR(20)  NOT NULL);
 
/* Insert the rows. */
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Hulk','Bruce','Banner');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Iron Man','Tony','Stark');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Black Widow','Natasha','Romanoff');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Thor','Thor','Odinsson');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Captain America','Steve','Rogers');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Hawkeye','Clint','Barton');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Winter Soldier','Bucky','Barnes');
INSERT INTO studentdb.marvel (avenger_name, first_name, last_name) VALUES ('Iron Patriot','James','Rhodey');
 
/* Query the contents of the MARVEL table. */
SELECT * FROM studentdb.marvel;

Written by maclochlainn

February 14th, 2015 at 5:20 pm

Filtering String Dates

with 2 comments

A question came up about how to verify dates from a string without throwing a casting error because of a non-conforming date. You can throw a number of exceptions, and I wrote a function to filter bad string formats like the DD-MON-RR or DD-MON-YYYY.

The first one is for a day between 1 and the last day of month, which is:

ORA-01847: day of month must be between 1 and last day of month

An incorrect string for a month, raises the following error:

ORA-01843: not a valid month

A date format mask longer than a DD-MON-RR or DD-MON-YYYY raises the following exception:

ORA-01830: date format picture ends before converting entire input string

The verify_date function checks for non-conforming DD-MON-RR and DD-MON-YYYY date masks, and substitutes a SYSDATE value for a bad date entry:

CREATE OR REPLACE
  FUNCTION verify_date
  ( pv_date_in  VARCHAR2) RETURN DATE IS
  /* Local return variable. */
  lv_date  DATE;
BEGIN
  /* Check for a DD-MON-RR or DD-MON-YYYY string. */
  IF REGEXP_LIKE(pv_date_in,'^[0-9]{2,2}-[ADFJMNOS][ACEOPU][BCGLNPRTVY]-([0-9]{2,2}|[0-9]{4,4})$') THEN
    /* Case statement checks for 28 or 29, 30, or 31 day month. */
    CASE
      /* Valid 31 day month date value. */
      WHEN SUBSTR(pv_date_in,4,3) IN ('JAN','MAR','MAY','JUL','AUG','OCT','DEC') AND
           TO_NUMBER(SUBSTR(pv_date_in,1,2)) BETWEEN 1 AND 31 THEN 
        lv_date := pv_date_in;
      /* Valid 30 day month date value. */
      WHEN SUBSTR(pv_date_in,4,3) IN ('APR','JUN','SEP','NOV') AND
           TO_NUMBER(SUBSTR(pv_date_in,1,2)) BETWEEN 1 AND 30 THEN 
        lv_date := pv_date_in;
      /* Valid 28 or 29 day month date value. */
      WHEN SUBSTR(pv_date_in,4,3) = 'FEB' THEN
        /* Verify 2-digit or 4-digit year. */
        IF (LENGTH(pv_date_in) = 9 AND MOD(TO_NUMBER(SUBSTR(pv_date_in,8,2)) + 2000,4) = 0 OR
            LENGTH(pv_date_in) = 11 AND MOD(TO_NUMBER(SUBSTR(pv_date_in,8,4)),4) = 0) AND
            TO_NUMBER(SUBSTR(pv_date_in,1,2)) BETWEEN 1 AND 29 THEN
          lv_date := pv_date_in;
        ELSE /* Not a leap year. */
          IF TO_NUMBER(SUBSTR(pv_date_in,1,2)) BETWEEN 1 AND 28 THEN
            lv_date := pv_date_in;
          ELSE
            lv_date := SYSDATE;
          END IF;
        END IF;
      ELSE
        /* Assign a default date. */
        lv_date := SYSDATE;
    END CASE;
  ELSE
    /* Assign a default date. */
    lv_date := SYSDATE;
  END IF;
  /* Return date. */
  RETURN lv_date;
END;
/

You can check valid dates with a DD-MON-RR format:

SELECT verify_date('28-FEB-10') AS "Non-Leap Year"
,      verify_date('29-FEB-12') AS "Leap Year"
,      verify_date('31-MAR-14') AS "31-Day Year"
,      verify_date('30-APR-14') AS "30-Day Year"
FROM   dual;

You can check valid dates with a DD-MON-YYYY format:

SELECT verify_date('28-FEB-2010') AS "Non-Leap Year"
,      verify_date('29-FEB-2012') AS "Leap Year"
,      verify_date('31-MAR-2014') AS "31-Day Year"
,      verify_date('30-APR-2014') AS "30-Day Year"
FROM   dual;

They both return:

Non-Leap    Leap YEAR 31-DAY YEAR 30-DAY YEAR
----------- --------- ----------- -----------
28-FEB-10   29-FEB-12 31-MAR-14   30-APR-14

You can check badly formatted dates with the following query:

SELECT verify_date('28-FEB-2010') AS "Non-Leap Year"
,      verify_date('29-FEB-2012') AS "Leap Year"
,      verify_date('31-MAR-2014') AS "31-Day Year"
,      verify_date('30-APR-2014') AS "30-Day Year"
FROM   dual;

You can screen for an alphanumeric string with the following expression:

SELECT 'Valid alphanumeric string literal' AS "Statement"
FROM   dual
WHERE  REGEXP_LIKE('Some Mythical String $200','([:alnum:]|[:punct:]|[:space:])*');

You can screen for a numeric literal as a string with the following expression:

SELECT 'Valid numeric literal' AS "Statement"
FROM   dual
WHERE  REGEXP_LIKE('123.00','([:digit:]|[:punct:])');

As always, I hope this helps those who need this type of solution.

Written by maclochlainn

February 2nd, 2015 at 12:53 am

Convert to SQL Server?

with 2 comments

I’m always amazed at the questions that pop up for me. For example, how do you convert an Oracle script that creates my Video Store model to a Microsoft SQL Server script. It’s not very hard but there’s one big caveat, and that’s the fact that system_user is a reserved word. That means you can’t create the Access Control List (ACL) table with a system_user name. The alternative, would be to convert the system_user table name to database_user. That’s what I’ve done in this example.

It’s also important to note that this example uses Microsoft SQL Server’s sqlcmd in batch mode. Naturally, it presumes that you’ve created a student user with a trivial password of student, and a studentdb schema. Also, that you’ve granted privileges so everything works (if you need help on that check my earlier post on how to setup a studentdb schema).

The following is an example of conditionally dropping and then creating a system_user table in an Oracle schema. It uses a CASCADE CONSTRAINTS clause to eliminate dependencies with foreign key values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Conditionally drop the table and sequence.
BEGIN
  FOR i IN (SELECT NULL
            FROM   user_tables
            WHERE  table_name = 'SYSTEM_USER') LOOP
    EXECUTE IMMEDIATE 'DROP TABLE system_user CASCADE CONSTRAINTS';
  END LOOP;
  FOR i IN (SELECT NULL
            FROM   user_sequences
            WHERE  sequence_name = 'SYSTEM_USER_S1') LOOP
    EXECUTE IMMEDIATE 'DROP SEQUENCE system_user_s1';
  END LOOP;
END;
/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--  Create SYSTEM_USER table.
CREATE TABLE system_user
( system_user_id            NUMBER        CONSTRAINT system_user_pk PRIMARY KEY
, system_user_name          VARCHAR2(20)  CONSTRAINT system_user_nn1 NOT NULL
, system_user_group_id      NUMBER        CONSTRAINT system_user_nn2 NOT NULL
, system_user_type          NUMBER        CONSTRAINT system_user_nn3 NOT NULL
, first_name                VARCHAR2(20)
, middle_name               VARCHAR2(20)
, last_name                 VARCHAR2(20)
, created_by                NUMBER        CONSTRAINT system_user_nn4 NOT NULL
, creation_date             DATE          CONSTRAINT system_user_nn5 NOT NULL
, last_updated_by           NUMBER        CONSTRAINT system_user_nn6 NOT NULL
, last_update_date          DATE          CONSTRAINT system_user_nn7 NOT NULL
, CONSTRAINT system_user_fk1  FOREIGN KEY (created_by)
  REFERENCES system_user (system_user_id)
, CONSTRAINT system_user_fk2  FOREIGN KEY (last_updated_by)
  REFERENCES system_user (system_user_id));
 
-- Create SYSTEM_USER_S1 sequence with a start value of 1001.
CREATE SEQUENCE system_user_s1 START WITH 1001;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- Conditionally drop the table and sequence.
BEGIN
  FOR i IN (SELECT NULL
            FROM   user_tables
            WHERE  table_name = 'COMMON_LOOKUP') LOOP
    EXECUTE IMMEDIATE 'DROP TABLE common_lookup CASCADE CONSTRAINTS';
  END LOOP;
  FOR i IN (SELECT NULL
            FROM   user_sequences
            WHERE  sequence_name = 'COMMON_LOOKUP_S1') LOOP
    EXECUTE IMMEDIATE 'DROP SEQUENCE common_lookup_s1';
  END LOOP;
END;
/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--  Create COMMON_LOOKUP table.
CREATE TABLE common_lookup
( common_lookup_id            NUMBER
, common_lookup_context       VARCHAR2(30) CONSTRAINT nn_clookup_1 NOT NULL
, common_lookup_type          VARCHAR2(30) CONSTRAINT nn_clookup_2 NOT NULL
, common_lookup_meaning       VARCHAR2(30) CONSTRAINT nn_clookup_3 NOT NULL
, created_by                  NUMBER       CONSTRAINT nn_clookup_4 NOT NULL
, creation_date               DATE         CONSTRAINT nn_clookup_5 NOT NULL
, last_updated_by             NUMBER       CONSTRAINT nn_clookup_6 NOT NULL
, last_update_date            DATE         CONSTRAINT nn_clookup_7 NOT NULL
, CONSTRAINT pk_c_lookup_1    PRIMARY KEY(common_lookup_id)
, CONSTRAINT fk_c_lookup_1    FOREIGN KEY(created_by) REFERENCES system_user(system_user_id)
, CONSTRAINT fk_c_lookup_2    FOREIGN KEY(last_updated_by) REFERENCES system_user(system_user_id));
 
-- Create a non-unique index on a single column.
CREATE INDEX common_lookup_n1
  ON common_lookup(common_lookup_context);
 
-- Create a unique index based on two columns.
CREATE UNIQUE INDEX common_lookup_u2
  ON common_lookup(common_lookup_context,common_lookup_type);
 
-- Create COMMON_LOOKUP_S1 sequence with a start value of 1001.
CREATE SEQUENCE common_lookup_s1 START WITH 1001;

You can do the same thing for a database_user table in Microsoft SQL Server with the following syntax. Unfortunately, there isn’t a CASCADE CONSTRAINTS clause that we can append in Microsoft SQL Server. The script uses a dynamic SQL statement with a Common Table Expression (CTE) to generate a list of ALTER statements that drop foreign key constraints in the schema.

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
/* Drop all foreign keys. */
USE studentdb;
 
/* Create a session variable to hold a command list. */
SELECT 'Create a session variable.' AS "Statement";
DECLARE @sql NVARCHAR(MAX) = N'';
 
/* Generate the command list to drop foreign key constraints. */
SELECT 'Generate dynamic SQL statements.' AS "Statement";
;WITH x AS
(SELECT N'ALTER TABLE ' +
          OBJECT_SCHEMA_NAME(parent_object_id) + N'.' +
          OBJECT_NAME(parent_object_id) + N' ' +
        N'DROP CONSTRAINT ' + name + N';' AS sqlstmt
 FROM     sys.foreign_keys)
SELECT @sql += sqlstmt FROM x;
 
/* Call the dynamically generated statements. */
SELECT 'Execute dynamic SQL statements.' AS "Statement";
EXEC sp_executesql @sql;
 
/* Conditionally drop tables. */
SELECT 'Conditionally drop studentdb.common_lookup table.' AS "Statement";
IF OBJECT_ID('studentdb.database_user','U') IS NOT NULL
  DROP TABLE studentdb.database_user;
 
/* Create a table with self-referencing foreign key constraints. */
SELECT 'Create studentdb.common_lookup table.' AS "Statement";
CREATE TABLE studentdb.database_user
( database_user_id        INT          NOT NULL IDENTITY(1,1) CONSTRAINT database_user_pk PRIMARY KEY
, database_user_name      VARCHAR(20)  NOT NULL
, database_user_group_id  INT          NOT NULL
, database_user_type      INT          NOT NULL
, first_name              VARCHAR(20)
, middle_name             VARCHAR(20)
, last_name               VARCHAR(20)
, created_by              INT          NOT NULL
, creation_date           DATE         NOT NULL
, last_updated_by         INT          NOT NULL
, last_update_date        DATE         NOT NULL
, CONSTRAINT database_user_fk1 FOREIGN KEY (created_by)
  REFERENCES studentdb.database_user (database_user_id)
, CONSTRAINT database_user_fk2 FOREIGN KEY (created_by)
  REFERENCES studentdb.database_user (database_user_id));
 
/* Conditionally drop common_lookup table. */
SELECT 'Conditionally drop studentdb.common_lookup table.' AS "Statement";
IF OBJECT_ID('studentdb.common_lookup','U') IS NOT NULL
  DROP TABLE studentdb.common_lookup;
 
/* Create a table with external referencing foreign key constraints. */  
SELECT 'Create studentdb.common_lookup table.' AS "Statement";
CREATE TABLE studentdb.common_lookup
( common_lookup_id            INT          NOT NULL  IDENTITY(1,1) CONSTRAINT common_lookup_pk PRIMARY KEY
, common_lookup_context       VARCHAR(30)  CONSTRAINT nn_clookup_1 NOT NULL
, common_lookup_type          VARCHAR(30)  CONSTRAINT nn_clookup_2 NOT NULL
, common_lookup_meaning       VARCHAR(30)  CONSTRAINT nn_clookup_3 NOT NULL
, created_by                  INT          CONSTRAINT nn_clookup_4 NOT NULL
, creation_date               DATE         CONSTRAINT nn_clookup_5 NOT NULL
, last_updated_by             INT          CONSTRAINT nn_clookup_6 NOT NULL
, last_update_date            DATE         CONSTRAINT nn_clookup_7 NOT NULL
, CONSTRAINT common_lookup_fk1 FOREIGN KEY(created_by)
  REFERENCES studentdb.database_user (database_user_id)
, CONSTRAINT common_lookup_fk2 FOREIGN KEY(last_updated_by)
  REFERENCES studentdb.database_user (database_user_id));

You can run it from a file by calling the sqlcmd utility. You’ll need to know several things to run it. First, you need to know your database instance. You can capture that from a query against the data dictionary or catalog. Just run the following from inside the Microsoft SQL Server Management Studio (SSMS):

SELECT @@SERVERNAME;

In my case, it shows the following, which is the machine’s hostname a backslash and SQLEXPRESS:

MCLAUGHLINSQL\SQLEXPRESS

The script uses sqltest.sql as a file name, and you can call it from the Windows shell environment like this:

sqlcmd -S MCLAUGHLINSQL\SQLEXPRESS -U student -P student -i C:\Data\MicrosoftSQL\sqltest.sql -o C:\Data\Microsoft\sqltest.out

As always, I hope this helps.

Written by maclochlainn

January 15th, 2015 at 7:18 pm

Querying an Object Type

without comments

I demonstrated a number of SQL approaches to reading object types in Appendix B of the Oracle Database 12c PL/SQL Programming book. For example, the easiest one to construct and return the results from a TO_STRING member function uses the TREAT function:

SELECT TREAT(base_t() AS base_t).to_string() AS "Text"
FROM   dual;

However, it seems that I could have provided one more. Here’s an example of how you can test the construction of an object type and how you can return its attributes with a query. It’s important to note that there’s a natural problem with this syntax when you increment a sequence inside the object type. The problem is that it double increments the counter for the sequence.

SELECT *
FROM   TABLE(SELECT CAST(COLLECT(base_t()) AS base_t_tab)
             FROM dual);

The syntax for the COLLECT function requires that you put it inside a SELECT-list. Then, the CAST function converts a single instance of the BASE_T object type to a one element BASE_T_TAB collection. Finally, the TABLE function returns a single row from the BASE_T_TAB collection.

You can find a more complete article covering column substitutability and object types and subtypes on the ToadWorld site. I think it helps clear up how you can effectively write PL/SQL types and subtypes for persistent object type columns.

Written by maclochlainn

November 25th, 2014 at 12:33 am