วันอังคารที่ 17 กันยายน พ.ศ. 2556

APEX 4.2.3 - อัพเกรด APEX บนฐานข้อมูล 12c (Oracle Multitenant)

วันนี้ได้อ่าน Oracle Application Express 4.2.3 now available ผมได้เห็นการอัพเกรด APEX บนฐานข้อมูล 12c (Oracle Multitenant). ล่าสุดก่อนหน้านี้ผมได้ลองใช้ patch ที่มีแต่ก็ยังไม่สามารถทำการอัพเกรด APEX ทีเดียวใน CDB$ROOT, PDB$SEED และ PDB... หลังจากผมได้ดาวน์โหลด patch 17347169 ก็ได้เวลาในการทดสอบ
ขั้นตอนแรกก็คือติดตั้ง Patch Set ใน CDB.
SQL> select CON_ID, NAME, OPEN_MODE from v$pdbs;

    CON_ID NAME                           OPEN_MODE
---------- ------------------------------ ----------
         2 PDB$SEED                       READ ONLY
         3 TESTPDB01                      READ WRITE

SQL> select COMP_ID, VERSION, CON_ID from cdb_registry where COMP_ID='APEX';

COMP_ID                        VERSION                            CON_ID
------------------------------ ------------------------------ ----------
APEX                           4.2.0.00.27                             1
APEX                           4.2.0.00.27                             2
APEX                           4.2.0.00.27                             3

[oracle@test12c ~]$ ls -l p17347169_423_Generic.zip
-rw-r--r--. 1 oracle oinstall 77044627 Sep 17 17:25 p17347169_423_Generic.zip
[oracle@test12c ~]$ unzip -l p17347169_423_Generic.zip |tail
     1197  09-11-2013 02:16   patch/patches/4_2_3/prereq.sql
     1812  07-13-2013 01:55   patch/patches/4_2_3/syspatch.sql
   144074  09-17-2013 00:45   patch/readme.htm
   220231  09-17-2013 00:45   patch/readme.pdf
        0  09-11-2013 04:59   patch/utilities/
     1621  08-31-2013 13:38   patch/utilities/reset_image_prefix.sql
     2804  08-31-2013 13:38   patch/utilities/reset_image_prefix_con.sql
     2575  08-31-2013 13:38   patch/utilities/reset_image_prefix_core.sql
---------                     -------
184039056                     11743 files
[oracle@test12c ~]$ unzip -l p17347169_423_Generic.zip
[oracle@test12c ~]$ ls patch/
apex_rest_config_con.sql   apex_rest_config.sql  apxldimg.sql      apxpatch.sql  images   readme.htm  utilities
apex_rest_config_core.sql  apxldimg_con.sql      apxpatch_con.sql  core          patches  readme.pdf
[oracle@test12c ~]$ cd patch/
[oracle@test12c patch]$

[oracle@test12c patch]$ ls -l apxpatch_con.sql
-rw-r--r--. 1 oracle oinstall 2496 Aug 31 13:38 apxpatch_con.sql
[oracle@test12c patch]$ pwd
/home/oracle/patch
[oracle@test12c patch]$ sqlplus  /nolog

SQL*Plus: Release 12.1.0.1.0 Production on Tue Sep 17 22:32:46 2013

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

SQL> connect / as sysdba
Connected.
SQL> @apxpatch_con.sql
PL/SQL procedure successfully completed.

Performing installation in multitenant container database in the background.
The installation progress is spooled into *patch_con*.log files.

Please wait...

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

timing for: Complete Patch
Elapsed: 01:29:21.57

Installation completed. Log files for each container can be found in:

syspatch_con*.log
ddlpatch_con*.log
deppatch_con*.log
corepatch_con*.log

You can quickly scan for ORA errors or compilation errors by using a utility
like grep:

grep ORA- *.log
grep PLS- *.log

SQL>
SQL> !grep ORA- *.log

SQL>
!grep PLS- *.log

SQL> select COMP_ID, VERSION, CON_ID from cdb_registry where COMP_ID='APEX';

COMP_ID                        VERSION                            CON_ID
------------------------------ ------------------------------ ----------
APEX                           4.2.3.00.08                             1
APEX                           4.2.3.00.08                             3
APEX                           4.2.3.00.08                             2
หลังจากนั้นอัพเดทรูปใน CDB ถ้าใช้ Embedded PL/SQL Gateway.
SQL> @apxldimg_con.sql /home/oracle/patch

PL/SQL procedure successfully completed.

Performing installation in multitenant container database in the background.
The installation progress is spooled into apxldimg_con*.log files.

Please wait...

/bin/bash: -c: line 0: syntax error near unexpected token `&'
/bin/bash: -c: line 0: `&OH_HOME/perl/bin/perl -I &OH_HOME/rdbms/admin &OH_HOME/rdbms/admin/catcon.pl -b apxldimg_con apxldimg.sql --p&1'


Installation completed. Log files for each container can be found in:

apxldimg_con*.log

You can quickly scan for ORA errors or compilation errors by using a utility
like grep:

grep ORA- *.log
grep PLS- *.log

SQL> exit
Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
[oracle@test12c patch]$ less apxldimg_con.sql
[oracle@test12c patch]$ less  apxpatch_con.sql
[oracle@test12c patch]$ sqlplus  /nolog

SQL*Plus: Release 12.1.0.1.0 Production on Wed Sep 18 00:08:06 2013

Copyright (c) 1982, 2013, Oracle.  All rights reserved.

SQL> conn / as sysdba
Connected.
SQL>  @apxldimg_con.sql /home/oracle/patch

PL/SQL procedure successfully completed.

Performing installation in multitenant container database in the background.
The installation progress is spooled into apxldimg_con*.log files.

Please wait...

Installation completed. Log files for each container can be found in:

apxldimg_con*.log

You can quickly scan for ORA errors or compilation errors by using a utility
like grep:

grep ORA- *.log
grep PLS- *.log

SQL>

เป็นอันสำเร็จด้วยดี

วันอาทิตย์ที่ 11 สิงหาคม พ.ศ. 2556

ทดสอบ 12c Default Values สำหรับคอลัมน์ (Sequence และ Explicit NULL Insertion)

บทความนี้ไม่ต้องการเกริ่นอะไรมาก ดังที่เราทราบกันดีว่า ฐานข้อมูลออราเคิล 12c เราสามารถเซตคอลัมน์กับ default values (บน Sequence และ Explicit NULL Insertion).
ออราเคิล sequence - เราสามารถระบุ sequence.CURVAL หรือ sequence.NEXTVAL
ออราเคิล Explicit NULL Insertion (ON NULL...) - เราสามารถระบุค่า default ที่เราต้องการเมื่อ INSERT กับค่า NULL  
ตัวอย่าง ผมขอใช้ทั้งสองกรณีในทีเดียวเลยนะครับ
SQL> CREATE SEQUENCE S1 START WITH 1;

Sequence created.

SQL> CREATE TABLE TB (ID NUMBER DEFAULT S1.NEXTVAL NOT NULL, NAME VARCHAR2(30), ADDR VARCHAR2(50) DEFAULT ON NULL 'N/A' NOT NULL);

Table created.

SQL> DESC TB
 Name                                                                                Null?    Type
 --------------- -------- --------------------------------------------------------
 ID                                                                                  NOT NULL NUMBER
 NAME                                                                                         VARCHAR2(30)
 ADDR                                                                                NOT NULL VARCHAR2(50)

SQL> INSERT INTO TB(NAME) VALUES('SURACHART OPUN');

1 row created.

SQL> INSERT INTO TB(NAME) VALUES('TEST!!!');

1 row created.

SQL> SELECT * FROM TB;

        ID NAME                           ADDR
---------- ------------------------------ --------------------------------------------------
         1 SURACHART OPUN                 N/A
         2 TEST!!!                        N/A

อ่านเพิ่มเติม Oracle Documents.

เรียนสร้างเทเบิลบนฐานข้อมูลออราเคิล 12c กับ Identity Column

วันนี้ได้มีโอกาสอ่านเกี่ยวกับการสร้างเทเบิลกับ  Identity คอลัมน์ ผมเกิดความสงสัยเลยลองหาข้อมูลและลองทดสอบดู จริงๆ แล้วคล้ายกับการที่เราสร้างเทเบิลแล้วมีการระบุ Sequence ให้กับคอลัมน์ที่ต้องการ อย่างไร? คิดง่ายๆ ว่า Option นี้ เข้ามาช่วยเราในการที่ไม่ต้องสร้าง Sequence เอง...

จะเห็นว่าเราสามารถเลือก ALWAYS (Oracle จะ generate ค่าของ sequence ทุกๆครั้ง เราไม่สามารถระบุค่าเองให้กับคอลัมน์นี้) และ BY DEFAULT (Oracle จะ generate ค่าของ sequence และเรายังสามารถระบุค่าในคอลัมน์นี้ได้เอง แต่ไม่สามารถระบุค่า NULL ยกเว้นเราใช้ BY DEFAULT ON NULL)
จำไว้ว่า  Identity คอลัมน์คือการสร้าง Sequence ดังนั้น USER ต้องมีสิทธิ์ในการสร้าง Sequence นะครับ

ขอใช้ตัวอย่างจาก Oracle Document มานำเสนอนะครับ
SQL> grant create table to demo;

Grant succeeded.

SQL> conn demo
Enter password:
Connected.
SQL> CREATE TABLE t1 (id NUMBER GENERATED AS IDENTITY, name varchar2(20));
CREATE TABLE t1 (id NUMBER GENERATED AS IDENTITY, name varchar2(20))
*
ERROR at line 1:
ORA-01031: insufficient privileges


SQL> conn / as sysdba
Connected.
SQL> grant create sequence to demo;

Grant succeeded.

SQL> conn demo
Enter password:
Connected.
SQL> CREATE TABLE t1 (id NUMBER GENERATED AS IDENTITY, name varchar2(20));

Table created.

SQL> select * from USER_TAB_IDENTITY_COLS;

TABLE_NAME                     COLUMN_NAME                    GENERATION
------------------------------ ------------------------------ ----------
IDENTITY_OPTIONS
------------------------------------------------------------------------------------------------------------------------------------------------------
T1                             ID                             ALWAYS
START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N, CACHE_SIZE: 20, ORDER_FLAG: N

SQL> select * from user_sequences;

SEQUENCE_NAME                   MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_92172                            1 1.0000E+28            1 N N         20           1                 N N

SQL> select * from T1;

no rows selected

SQL> desc T1
 Name                                                                                Null?    Type
 ----------------------------------------------------------------------------------- -------- --------------------------------------------------------
 ID                                                                                  NOT NULL NUMBER
 NAME                                                                                         VARCHAR2(20)

SQL> insert into T1(name) values('Surachart Opun');
1 row created.

SQL> select * from T1;

        ID NAME
---------- --------------------
         1 Surachart Opun

SQL> select * from user_sequences;

SEQUENCE_NAME                   MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_92172                            1 1.0000E+28            1 N N         20          21                 N N

SQL> insert into T1(name) values('Test Again!');

1 row created.

SQL>  select * from T1;

        ID NAME
---------- --------------------
         1 Surachart Opun
         2 Test Again!

SQL> select * from user_sequences;

SEQUENCE_NAME                   MIN_VALUE  MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER PARTITION_COUNT S K
------------------------------ ---------- ---------- ------------ - - ---------- ----------- --------------- - -
ISEQ$$_92172                            1 1.0000E+28            1 N N         20          21                 N N
ตัวอย่างอื่นๆ
SQL> CREATE TABLE t2 (id NUMBER GENERATED BY DEFAULT AS IDENTITY (START WITH 100 INCREMENT BY 10), Name varchar2(20));

Table created.

SQL> select * from USER_TAB_IDENTITY_COLS where table_name='T2';

TABLE_NAME                     COLUMN_NAME                    GENERATION
------------------------------ ------------------------------ ----------
IDENTITY_OPTIONS
------------------------------------------------------------------------------------------------------------------------------------------------------
T2                             ID                             BY DEFAULT
START WITH: 100, INCREMENT BY: 10, MAX_VALUE: 9999999999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N, CACHE_SIZE: 20, ORDER_FLAG: N


SQL> select * from t2;

no rows selected

SQL> insert into T2(name) values ('Chart');

1 row created.

SQL> select * from t2;

        ID NAME
---------- --------------------
       100 Chart

***************************************************************************
SQL> CREATE TABLE t3 (id NUMBER  GENERATED BY DEFAULT AS IDENTITY  , name varchar2(20));

Table created.

SQL> CREATE TABLE t4 (id NUMBER  GENERATED BY DEFAULT ON NULL AS IDENTITY , name varchar2(20));

Table created.

SQL>
SQL>
SQL> insert into T3 values(10,'TEST');

1 row created.

SQL> insert into T4 values(10,'TEST');

1 row created.

SQL> select * from T3;

        ID NAME
---------- --------------------
        10 TEST

SQL> c/3/4
  1* select * from T4
SQL> /

        ID NAME
---------- --------------------
        10 TEST

SQL> insert into T3(name) values ('Chart');

1 row created.

SQL> c/3/4
  1* insert into T4(name) values ('Chart')
SQL> /

1 row created.

SQL>  select * from T3;

        ID NAME
---------- --------------------
        10 TEST
         1 Chart

SQL> select * from T4
  2  /

        ID NAME
---------- --------------------
        10 TEST
         1 Chart

SQL>  insert into T3 values(NULL,'AAA');
 insert into T3 values(NULL,'AAA')
                       *
ERROR at line 1:
ORA-01400: cannot insert NULL into ("DEMO"."T3"."ID")


SQL> c/3/4
  1*  insert into T4 values(NULL,'AAA')
SQL> /

1 row created.

SQL> select * from t4;

        ID NAME
---------- --------------------
        10 TEST
         1 Chart
         2 AAA

SQL> CREATE TABLE t5  (id NUMBER  GENERATED ALWAYS AS IDENTITY , name varchar2(20));

Table created.

SQL> insert into T5 values(NULL,'AAA')
  2  /
insert into T5 values(NULL,'AAA')
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column


SQL> insert into T5 values(1,'AAA')
  2  /
insert into T5 values(1,'AAA')
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column


SQL>  insert into T5(name) values('TEST');

1 row created.

SQL> select * from T5;

        ID NAME
---------- --------------------
         1 TEST

หวังว่าจะมีประโยชน์กับเพื่อนๆ นะครับ