IDEAL NUMBER OF PARTITIONS ON A TABLE
Dear All,
I have a table with crores or records.Can anyone suggest the number of partitions that are ideal to make on a table keeping in view aboutperformance of queries?
Thanks,
Deepu.
In general partitioning is going to improve your select performance where you typically have many queries using predicates based on the same column, and the predicates return a significant number of rows such that accessing the table via an index-based method is inefficient.
For example if you have a table of sales history and users commonly access the data with a predicate such as ...
date_of_sale between sysdate -100 and sysdate - 50
So, do you have many queries that select a relatively high number of rows based on predicates on a common column?
Edit: By the way, 3Gb is not much data unless your hardware is really slow.
Message was edited by:
David Aldridge
Similar Messages
-
Maximum number of partitions allowed per table.
Interesting findings with interval partitioning:
SQL> SELECT *
2 FROM v$version
3 /
BANNER
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
SQL> DROP TABLE tbl PURGE
2 /
Table dropped.
SQL> CREATE TABLE tbl(
2 id number(6),
3 dt date
4 )
5 PARTITION BY RANGE(dt)
6 INTERVAL (INTERVAL '1' DAY)
7 (
8 PARTITION p1 VALUES LESS THAN (date '-857-12-31')
9 )
10 /
Table created.
SQL> select partition_name,
2 high_value
3 from user_tab_partitions
4 where table_name = 'TBL'
5 /
PARTITION_NAME HIGH_VALUE
P1 TO_DATE('-0857-12-31 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'N
LS_CALENDAR=GREGORIAN')
SQL> INSERT
2 INTO tbl
3 VALUES(
4 1,
5 sysdate
6 )
7 /
1 row created.
SQL> DROP TABLE tbl PURGE
2 /
Table dropped.
SQL> CREATE TABLE tbl(
2 id number(6),
3 dt date
4 )
5 PARTITION BY RANGE(dt)
6 INTERVAL (INTERVAL '1' DAY)
7 (
8 PARTITION p1 VALUES LESS THAN (date '-858-01-01')
9 )
10 /
Table created.
SQL> select partition_name,
2 high_value
3 from user_tab_partitions
4 where table_name = 'TBL'
5 /
PARTITION_NAME HIGH_VALUE
P1 TO_DATE('-0858-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'N
LS_CALENDAR=GREGORIAN')
SQL> INSERT
2 INTO tbl
3 VALUES(
4 1,
5 sysdate
6 )
7 /
INTO tbl
ERROR at line 2:
ORA-14300: partitioning key maps to a partition outside maximum permitted number of partitions
SQL> From Logical Database Limits:
Maximum number of partitions allowed per table or index: 1024K - 1
I always thought limit implies to number of actual, not potential partitions, however it looks like I was wrong, although it makes not much sense to limit potential and not actual partitions:
SQL> select trunc(sysdate) - date '-858-01-01',
2 1024 * 1024 - 1
3 from dual
4 /
TRUNC(SYSDATE)-DATE'-858-01-01' 1024*1024-1
1048661 1048575
SQL> select to_char(DATE'-858-01-01' + 1048575,'MM/DD/YYYY')
2 from dual
3 /
TO_CHAR(DA
11/17/2012
SQL> So tomorrow "magic" date should increase by one day. I'll test it. But more interesting if tomorrow I will be able to insert a row that forms a new partition into table TBL.
SY.rp0428 wrote:
The other argument is that Oracle has to be able to automatically create any partition required and it can only create 1024k - 1. So if you create yours with sysdate how could it create all of the others?Not sure I follow. What is the purpose of counting potential partitions? Partition part# iin sys.tabpart$ is not assigned based on potential partition position. If I issue a DDL to create new partition regardless of interval/non-interval partitioning Oracle has to check how many partitions table has so far or po and raise same/similar exception if partition I am asking to create is over the limit. And, in any case, knowing we can create all potential partitions at table create time doesn't mean I will not try to insert data outside the range. So there is absolutely no guarantee Oracle can automatically create any partition requested. Again, I don't understand why creating non-interval partitioned table with a single initial partition has partition count of 1:
SQL> DROP TABLE tbl1 PURGE
2 /
Table dropped.
SQL> CREATE TABLE tbl1(
2 id number(6),
3 dt date
4 )
5 PARTITION BY RANGE(dt)
6 (
7 PARTITION p1 VALUES LESS THAN (date '-857-12-31')
8 )
9 /
Table created.
SQL> SELECT partition_count
2 FROM user_part_tables
3 WHERE table_name = 'TBL1'
4 /
PARTITION_COUNT
1
SQL>And interval partitioned table with same single initial partition has partition count of 1048575:
SQL> CREATE TABLE tbl1(
2 id number(6),
3 dt date
4 )
5 PARTITION BY RANGE(dt)
6 INTERVAL (INTERVAL '1' DAY)
7 (
8 PARTITION p1 VALUES LESS THAN (date '-857-12-31')
9 )
10 /
Table created.
SQL> SELECT partition_count
2 FROM user_part_tables
3 WHERE table_name = 'TBL1'
4 /
PARTITION_COUNT
1048575
SQL> Would be interesting to find out what forces Oracle to go into potential partition mode for interval partitioning.
SY. -
Limit on the number of partitions a table can have
Hi,
It's been quite some time I'm thinking of a simple and the best solution to a performance issue in my application. Benefiting out of partitioning the table seems a simplest approach; it involves very minimal changes to my application code and in addition, it keeps the overall application logic 100% intact. However, at times, the number of partitions required can grow to as large as 500 thousand. I know of another application implementing as many as 50 thousand partitions for one of its tables. I'm wondering if Oracle recommends or poses any limit to a number of partitions the table can have. How does that limit, if it exists, vary if each of my table partition holds only a small amount of data; say, not more than 2 thousand records each of 1 KB size. What are the important considerations that one needs to keep in mind while creating the huge number of partitions for a table?
Any inputs on this would be a great help.
Thanks,
Aniruddh
ps: Consider Oracle releases 10g onwards.
Edited by: Aniruddh on Dec 30, 2009 9:46 AM
Edited by: Aniruddh on Dec 30, 2009 9:50 AMAniruddh,
>
What are the important considerations that one needs to keep in mind while creating the huge number of partitions for a table?
>
I doubt if you are using partitioning for the right causes. Please explain how is your data structured and why you need to create so many partitions..?
when creating partition, you need to consider..
a) why you need to partition?
b) how is your data structured
c) how your data is indexed.
d) What kind of queries would you firing on this table to get the data. Will they use the partition key ?
Thanks,
Rajesh.
Please mark this/any other answer as helpful or answered if it is so. If not, provide additional details/feedback.
Always try to provide create table and insert statements to help the forum members help you better. -
Maximum No. of Partitions in a Table?
Hi,
What is the Maximum no.of partitions in a table?
Best Regards,
Naresh Kumar C.All resides in what is 1K ?
First option (more popular) : 1K=1024, so 1024K = 1024*1024
Second option (less popular) : 1K = 1000, 1024K = 1024*1000
http://en.wikipedia.org/wiki/Byte
Have you really need to 1024K-1 partitions (either one or other option, it's already huge for number of partitions) ? Good luck for maintenance tasks...
Nicolas. -
Problem in truncate/drop partitions in a table having nested table columns.
Hi,
I have a table that has 2 columns of type nested table. Now in the purge process, when I try to truncate or drop a partition from this table, I get error that I can't do this (because table has nested tables). Can anybody help me telling how I will be able to truncate/drop partition from this table? IF I change column types from nested table to varray type, will it help?
Also, is there any short method of moving existing data from a nested table column to a varray column (having same fields as nested table)?
Thanks in advance.>
I have a table that has 2 columns of type nested table. Now in the purge process, when I try to truncate or drop a partition from this table, I get error that I can't do this (because table has nested tables). Can anybody help me telling how I will be able to truncate/drop partition from this table?
>
Unfortunately you can't do those operations when a table has a nested table column. No truncate, no drop, no exchange partition at the partition level.
A nested table column is stored as a separate table and acts like a 'child' table with foreign keys to the 'parent' table. It is these 'foreign keys' that prevent the truncation (just like normal foreign keys prevent truncating partions and must be disabled first) but there is no mechanism to 'disable' them.
Just one excellent example (there are many others) of why you should NOT use object columns at all.
>
IF I change column types from nested table to varray type, will it help?
>
Yes but I STRONGLY suggest you take this opportunity to change your data model to a standard relational one and put the 'child' (nested table) data into its own table with a foreign key to the parent. You can create a view on the two tables that can make data appear as if you have a nested table type if you want.
Assuming that you are going to ignore the above advice just create a new VARRAY type and a table with that type as a column. Remember VARRAYs are defined with a maximum size. So the number of nested table records needs to be within the capacity of the VARRAY type for the data to fit.
>
Also, is there any short method of moving existing data from a nested table column to a varray column (having same fields as nested table)?
>
Sure - just CAST the nested table to the VARRAY type. Here is code for a VARRAY type and a new table that shows how to do it.
-- new array type
CREATE OR REPLACE TYPE ARRAY_T AS VARRAY(10) OF VARCHAR2(64)
-- new table using new array type - NOTE there is no nested table storage clause - arrays stored inline
CREATE TABLE partitioned_table_array
( ID_ INT,
arra_col ARRAY_T )
PARTITION BY RANGE (ID_)
( PARTITION p1 VALUES LESS THAN (40)
, PARTITION p2 VALUES LESS THAN(80)
, PARTITION p3 VALUES LESS THAN(100)
-- insert the data from the original table converting the nested table data to the varray type
INSERT INTO PARTITIONED_TABLE_ARRAY
SELECT ID_, CAST(NESTED_COL AS ARRAY_T) FROM PARTITIONED_TABLENaturally since there is no more nested table storage you can truncate or drop partitions in the above table
alter table partitioned_table_array truncate partition p1
alter table partitioned_table_array drop partition p1 -
Partition Manager is creating more than double number of partitions .
Dear Team,
I am facing a very weird scenario .
For one of my product , one of the section is the Partition Manager executing for the Tables . Now I am facing a problem and it is really getting difficult for me to get to the root cause and thus posting in the forum ...
I am having two Linux systems , in one of the system, installation of the product goes fine , and partition manager is doing the partition as intended .
In another Linux lab , ( with some extra application installed ) , the same product is failing to install , and the problem is Partition Manager is doing the partition more than double as compared to first Lab and because of this it ends up using all the space in the system .
My Concern is do we have any global setting for this Partition Manager in the Oracle Database , and because of this I am seeing the difference in this 2 labs ..I will be really thankful for any of the inputs and suggestion ...
With Very Best Regards,
Shail...
Edited by: 999908 on 13 Apr, 2013 9:27 PMHello Justin,
First of all thanks a lot for your patience ... :) , in looking into my problem ..
But I guess it is using Oracle partitioning Concept only...I dont think , my product is using the third party partition tool ( I will recheck this once to confirm )
What I understand is that , if for any table the number of partitions is almost thrice in one system as compared to other , then it will end up consuming more space for the table in the system where it is creating more number of partitions ...
I guess memory usage for any table also depends on the number of partitions ( Please do correct me if I am wrong here ) , if more number of partitions are there then more memory will be consumed , I guess..With Very Best Regards,
Shail -
Large (highest ?) Number of Partitions / SubPartitions in *Production*
In theory, the maximum number of Partitions/SubPartitions that Oracle supports for a table is 1024K-1 in 10gR2.
Per MetaLink Note#76765.1, the limit was 64K-1 in 8i -- and, I understand from the 9i docs, was also the same limit in 9i. The Note candidly admits that only 1,000 Partitions have been tested.
Have you implemented / seen implemented, say 64thousand Partitions for a table (and this being done for possibly half-a-dozen tables), with at leaste one corresponding LOCALly Partitioned Index ?
What are the implications on :
1. MetaData in the Shared Pool and Latching.
2. Gather_Stats (done GLOBAL or PARTITION wise).
3. Queries that, very unfortunately, end up scanning all the partitions, many of which are small 64K partitions only..
-
How can I partition an existing table? What's the SQL syntax?
Thanks for help,
Chen ZhaoDoes anybody know how to partition an existing table?
YES! That is the simple answer to your question. There are a lot of people that know how to do that.
Whether partitioning is appropriate and, if so, which method might be 'best' for YOU depends on the particulars of your use case. But as with most problems you need to make sure you troubleshoot whatever issue you have in the proper order:
1. Identify a PROBLEM or issue that needs to be resolved - you haven't told us anything. Please post info about this
2. Validate that the problem/issue actually exists (it could just be a fluke occurence)
3. Identify potential solutions to the problem/issue - that list of solutions may, or may not, include partitioning
4. Select a small number (e.g. 1 or 2) of those solutions for further analysis and actual tests.
5. Select the 'best' (based on your orgs criteria) of those tested solutions for implemention
You seem to already be on step #5. But in order for us to help you we have to understand what the results of steps 1 thru 4 are.
Please post the information about your PROBLEM that we need to help you. -
Maximum Number of ListPartitions on a Table.
Hi All,
I am having a table say here EMP_HISTORY which is going to have 1 Billion records.
ORACLE Version: 10gR2.
The table structure will be as given below.
EMP_HIST_ID NUMBER,
EMPNO NUMBER,
ENAME VARCHAR2(4000),
PREV_SAL NUMBER,
PREV_DEPTNO NUMBER,
PREV_COMM NUMBER
This historical table will have Millions of records and it will be inserting all the historical information of the employee information changes that are done on the EMP table.
Note: In My case the EMP table is having EMPNO as primary key and there are around 1000 UNIQUE employee NUMBERS.
I want to build reports basing upon this EMP_HISTORY table and I want to query the data for EMPNO.
In this case If I query on the EMPNO on the EMP_HISTORY table it is taking lots of time.
I am planning to do LIST Partition on this table and create 1000 list partitions on this Single EMP_HISTORY table.
Is it a good approach to create 1000 list partitions and add new partitions whenever new EMPNO are added to this history table.
OR Is there any OTHER Partition I can go for.
FYI: I am giving EMP_HISTORY table as an example. Our History table is also having the same structure.
FYI: I am just a developer and in our team we don't have any DB Designer and we are trying to do it by ourselves.
Appreciate your response on this.
Thanks,
Madhu K.569725 wrote:
Hi All,
I am having a table say here EMP_HISTORY which is going to have 1 Billion records.
ORACLE Version: 10gR2.
The table structure will be as given below.
EMP_HIST_ID NUMBER,
EMPNO NUMBER,
ENAME VARCHAR2(4000),
PREV_SAL NUMBER,
PREV_DEPTNO NUMBER,
PREV_COMM NUMBER
This historical table will have Millions of records and it will be inserting all the historical information of the employee information changes that are done on the EMP table.
Note: In My case the EMP table is having EMPNO as primary key and there are around 1000 UNIQUE employee NUMBERS.
I want to build reports basing upon this EMP_HISTORY table and I want to query the data for EMPNO.
In principle, the most effective strategy for addressing your requirements (or, at least, the ones you've described) in 10g is to create a list-partitioned index organized table with compression on the EMPNO.
I note that your table doesn't have a change timestamp, however, so I assume you are using a sequence generator to create the emp_hist_id. If this is the case you should make the (empno, emp_hist_id) the primary key of the IOT.
Regards
Jonathan Lewis
http://jonathanlewis.wordpress.com
http://www.jlcomp.demon.co.uk
To post code, statspack/AWR report, execution plans or trace files, start and end the section with the tag {noformat}{noformat} (lowercase, curly brackets, no spaces) so that the text appears in fixed format.
There is a +"Preview"+ tab at the top of the text entry panel. Use this to check what your message will look like before you post the message. If it looks a complete mess you're unlikely to get a response. (Click on the +"Plain text"+ tab if you want to edit the text to tidy it up.)
"Science is more than a body of knowledge; it is a way of thinking"
Carl Sagan -
Drop older ( more than 3days of ) partitions in a table
Hi Guru's,
I have created an HOURLY interval partitioning for a table and the management was decide to 3 days of retention policy. So i need to schedule a Cron job for removing older partitions older than 3days, but i am not sure, how to write a shell script or a procedure to do this. Please help me on this and below are the table syntax and the partitions.
CREATE TABLE TRANSACTION
ID NUMBER(18) NOT NULL ,
ACCT_ID NUMBER(18) NOT NULL ,
BANKING_ID NUMBER(18) NOT NULL ,
CREATED_DATE TIMESTAMP(3) NOT NULL ,
COMMISSION_AMOUNT NUMBER(15,2) NULL ,
CONFIRMATION_NO NVARCHAR2(255) NULL ,
CREATED_BY NVARCHAR2(255) NOT NULL ,
CREATED_TS TIMESTAMP(3) NOT NULL ,
MODIFIED_BY NVARCHAR2(255) NOT NULL ,
MODIFIED_TS TIMESTAMP(3) NOT NULL
PARTITION BY RANGE ("CREATED_TS") INTERVAL( NUMTODSINTERVAL(1, 'HOUR'))
( PARTITION TRANS_DATA VALUES LESS THAN (TO_DATE(' 2011-11-04 20:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P,
PARTITION TRANS_DATA1 VALUES LESS THAN (TO_DATE(' 2011-11-04 21:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P1,
PARTITION TRANS_DATA2 VALUES LESS THAN (TO_DATE(' 2011-11-04 22:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P2,
PARTITION TRANS_DATA3 VALUES LESS THAN (TO_DATE(' 2011-11-04 23:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P3,
PARTITION TRANS_DATA4 VALUES LESS THAN (TO_DATE(' 2011-11-05 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P4,
PARTITION TRANS_DATA5 VALUES LESS THAN (TO_DATE(' 2011-11-05 01:00:00', 'YYYY-MM-DD HH24:MI:SS') ) TABLESPACE &&TABLE_TS_P5
Here Partitioning key is "CREATED_TS".
HERE are the partitions created for this table.
HIGH_VALUE PARTITION_NAME
TIMESTAMP' 2011-11-04 20:00:00' TRANS_DATA
TIMESTAMP' 2011-11-04 21:00:00' TRANS_DATA1
TIMESTAMP' 2011-11-04 22:00:00' TRANS_DATA2
TIMESTAMP' 2011-11-04 23:00:00' TRANS_DATA3
TIMESTAMP' 2011-11-05 00:00:00' TRANS_DATA4
TIMESTAMP' 2011-11-05 01:00:00' TRANS_DATA5
TIMESTAMP' 2011-11-05 02:00:00' SYS_P41
TIMESTAMP' 2011-11-05 03:00:00' SYS_P42
TIMESTAMP' 2011-11-05 04:00:00' SYS_P44
TIMESTAMP' 2011-11-05 05:00:00' SYS_P46
TIMESTAMP' 2011-11-05 06:00:00' SYS_P49
TIMESTAMP' 2011-11-05 07:00:00' SYS_P52
TIMESTAMP' 2011-11-05 08:00:00' SYS_P102
TIMESTAMP' 2011-11-05 09:00:00' SYS_P121
TIMESTAMP' 2011-11-05 10:00:00' SYS_P141
TIMESTAMP' 2011-11-05 11:00:00' SYS_P144
TIMESTAMP' 2011-11-05 12:00:00' SYS_P147
TIMESTAMP' 2011-11-05 13:00:00' SYS_P149
TIMESTAMP' 2011-11-05 14:00:00' SYS_P151
TIMESTAMP' 2011-11-05 15:00:00' SYS_P152
TIMESTAMP' 2011-11-05 16:00:00' SYS_P154
TIMESTAMP' 2011-11-05 17:00:00' SYS_P157
TIMESTAMP' 2011-11-05 18:00:00' SYS_P222
TIMESTAMP' 2011-11-05 19:00:00' SYS_P159
TIMESTAMP' 2011-11-05 20:00:00' SYS_P243
TIMESTAMP' 2011-11-05 21:00:00' SYS_P261
TIMESTAMP' 2011-11-05 22:00:00' SYS_P282
TIMESTAMP' 2011-11-06 01:00:00' SYS_P285
TIMESTAMP' 2011-11-06 02:00:00' SYS_P303
TIMESTAMP' 2011-11-06 03:00:00' SYS_P287
TIMESTAMP' 2011-11-06 04:00:00' SYS_P289
TIMESTAMP' 2011-11-06 05:00:00' SYS_P307
TIMESTAMP' 2011-11-06 06:00:00' SYS_P324
TIMESTAMP' 2011-11-06 07:00:00' SYS_P310
TIMESTAMP' 2011-11-06 08:00:00' SYS_P313
TIMESTAMP' 2011-11-06 09:00:00' SYS_P342
TIMESTAMP' 2011-11-06 10:00:00' SYS_P292
TIMESTAMP' 2011-11-06 11:00:00' SYS_P315
TIMESTAMP' 2011-11-06 12:00:00' SYS_P295
TIMESTAMP' 2011-11-06 13:00:00' SYS_P298
TIMESTAMP' 2011-11-06 14:00:00' SYS_P361
TIMESTAMP' 2011-11-06 15:00:00' SYS_P363
TIMESTAMP' 2011-11-06 16:00:00' SYS_P365
TIMESTAMP' 2011-11-06 17:00:00' SYS_P366
TIMESTAMP' 2011-11-06 18:00:00' SYS_P368
TIMESTAMP' 2011-11-06 19:00:00' SYS_P371
TIMESTAMP' 2011-11-06 20:00:00' SYS_P373
Here the partition names are not in order, so i am not able to figure out, to do the syntax to drop the partitions. Please let me know, how to drop the older partitions.You can use partition_position from user_tab_partitions to determine how many partitions you want to drop and which ones. These are always in order, regardless of your partition names. This obviously assumes that all your partitions are uniform (hourly in your case).
Milina -
Partitioning (range) a table values less than 'A'
i am referring
http://docs.oracle.com/cd/B10501_01/server.920/a96524/c12parti.htm
http://docs.oracle.com/cd/B19306_01/server.102/b14220/partconc.htm
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
"CORE 10.2.0.1.0 Production"
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
create table drop_it as select * from mv_prod_search_det2;
CREATE TABLE DROP_IT_P(
PROD_DETAILS VARCHAR2(1000 BYTE),
SIGN VARCHAR2(42 BYTE)
PARTITION BY RANGE(PROD_DETAILS)
PARTITION MAX_VALUE VALUES LESS THAN (MAXVALUE)
update drop_it set prod_details=upper(prod_details);
72000 rows updated
ALTER TABLE drop_it_p EXCHANGE PARTITION MAX_VALUE WITH TABLE drop_it WITH VALIDATION;
select * from mv_prod_search_det2
72000 rows selected
exec dbms_stats.gather_database_stats;
select * from drop_it_p partition(max_value)
ALTER TABLE DROP_IT_P
SPLIT PARTITION MAX_VALUE AT ('B%')
INTO (PARTITION p_a,
PARTITION MAX_VALUE);
select * from drop_it_p partition(p_a);
6785 rows selected
select * from drop_it_p partition(p_a) where prod_details not like 'A%'
696 rows selectedit even shows me values that start with W,V,I,1,2,3,4,24,5 etc
although the number is less(696out of 6785) this is undesired
please help me eliminate these rows
thank you
this thread is related to tuning regexp_like by author 946207
please refer
tuning regexp_like
and partitioning a table by 946207
Edited by: 946207 on Dec 2, 2012 1:52 AM
Edited by: 946207 on Dec 2, 2012 11:02 PMFirst, when you post related threads you should cross-link them so people have access to all of the information about the problem you are trying to work with.
partitioning a table
>
it even shows me values that start with W,V,I,1,2,3,4,24,5 etc
although the number is less(696out of 6785) this is undesired
>
Yes - that is what it should be doing.
These are the steps you took to populate the table
1. You originally inserted ALL data into table 'drop_it' with no restriction on the PROD_DETAILS values.
create table drop_it as select * from mv_prod_search_det2; 2. Then you converted the PROD_DETAILS value to upper case. That has no effect on numbers or other non-alphabetic characters.
update drop_it set prod_details=upper(prod_details);3. Then you create a new table with only one partition using MAXVALUe
PROD_DETAILS VARCHAR2(1000 BYTE),
SIGN VARCHAR2(42 BYTE)
PARTITION BY RANGE(PROD_DETAILS)
PARTITION MAX_VALUE VALUES LESS THAN (MAXVALUE)
);4. Then you populate the partitioned table by exchange. It now has the same data including the numeric data.
ALTER TABLE drop_it_p EXCHANGE PARTITION MAX_VALUE WITH TABLE drop_it WITH VALIDATION; 5. Then you split the one MAXVALUE partition into two partitions. One with data < 'B%' and one with the remaining data that sorts higher based on your character set.
ALTER TABLE DROP_IT_P
SPLIT PARTITION MAX_VALUE AT ('B%')
INTO (PARTITION p_a,
PARTITION MAX_VALUE); The split on 'B%' when creating partition p_a is equivalent to you 'WITH VALUES < 'B%'. Since PROD_DETAILS is a VARCHAR2 datatype that 'LESS THAN' comparison uses the character order based on your database character set and most, if not all, character sets have characters that sort lower than the uppercase alphabetic characters.
For example in the ASCII character set an uppercase 'A' is decimal 65 so 64 other characters (including the digitis 0-9) sort lower than 'A'.
http://www.asciitable.com/
As the doc you cited shows
>
•All partitions, except the first, have an implicit lower bound specified by the VALUES LESS THAN clause on the previous partition.
>
That 'first' partition has no lower bound so ALL data, including digits, that sort less than 'B%' will be in that partition.
>
please help me eliminate these rows
>
Either don't select the data to begin with or remove it using a simple DELETE query. Also you can do the case conversion when you select the data.
create table drop_it as select upper(prod_details) prod_details, sign from mv_prod_search_det2 where upper(prod_details >= 'A';Before you do that you should make sure you define the actual business rule you want to use to define the data you really want to keep and exclude.
Because most, if not all, character sets also have characters that sort HIGHER than the alphabetic characters. That ASCII table shows five of them. If you don't filter them out you will get data where the values start with those characters.
Even if you do filter them out there is nothing in what you posted that would prevent a user from inserting that data back into the table.
And, of course, there are characters that sort BETWEEN the lower and upper case alphabetics.
You need to determine what the allowable characters are in the PROD_DETAILS column and add code (e.g. check constraint or trigger) to make sure users can't enter data that includes those characters. -
Partitioning the OKL_STRM_ELEMENTS table
I am looking for someone with experience with partitioning the OKL_STRM_ELEMENTS table. I would like to know what you partitioned on and if you had any problems once you implemented the partitions. Besides the OKL_STRM_ELEMENTS table are there any other Lease Management table that should be partitioned.
BLCThis is documentation of the Partitioning the OKL_STRM_ELEMENTS table
You should made a proposal to partition the table based on STREAM_ELEMENT_DATE Performance team however suggested creating a larger number of partitions using a smaller range (MMYYYY vs YYYY) rather than using a subpartition by hash(ID).
Performance benefits may be seen in SQL statements that take advantage of the partioning scheme resulting in partition elimination (i.e. the sqls actually scan less data), this happens for sqls that have the partition key in the WHERE clause.
Partitioning a table can actually degrade overall performance if the SQL statements referencing this table do not include the partition key in the WHERE clause as a filter. The performance degradation is caused by the fact that the query has to scan several partitions as opposed to a single segment in the non-partitioned case.
The majority of select statements on OKL_STRM_ELEMENTS in OKL do include STREAM_ELEMENT_DATE in the where clause, so overall benefit should be positive.
Moreover, ranges should be based on analysis of your data distribution -
How to find number of rows in a table
i have one table ,it contains millions of record,how can i know number of rows in that table without using count(*),
i tried in user_table ,for the column NUM_ROWS,but it is not showing number of rows,pls send me a solution for this.
regards,
singhOk, that only was to show simply that max option
might not an option to reduce execution time.Yes, but I/O variances have a tendency to really skew the observed elapsed execution time - making execution time alone a poor choice to determine what SQL will perform better than another.
Both MAX(ROWNUM) and COUNT(*) results in the same amount of I/O - as both uses the exact same execution plan, I/O wise. In this example, a FTS.
SQL> create table testtab nologging as select * from all_objects where rownum < 10001;
Table created.
-- warmed up the buffer cache with a couple of SELECTs against TESTAB in order
-- to discard PIOs from the results
SQL> set autotrace on
SQL> select count(*) from testtab;
COUNT(*)
10000
Execution Plan
Plan hash value: 2656308840
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 35 (9)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| TESTTAB | 9262 | 35 (9)| 00:00:01 |
Note
- dynamic sampling used for this statement
Statistics
0 recursive calls
0 db block gets
131 consistent gets
0 physical reads
0 redo size
223 bytes sent via SQL*Net to client
238 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select max(rownum) from testtab;
MAX(ROWNUM)
10000
Execution Plan
Plan hash value: 2387991791
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 35 (9)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | COUNT | | | | |
| 3 | TABLE ACCESS FULL| TESTTAB | 9262 | 35 (9)| 00:00:01 |
Note
- dynamic sampling used for this statement
Statistics
0 recursive calls
0 db block gets
131 consistent gets
0 physical reads
0 redo size
225 bytes sent via SQL*Net to client
238 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
So seeing that we have the exact same baseline for both queries, and that PIO does not influence the results, we time a 1000 executions of both.
SQL> declare
2 cnt number;
3 begin
4 for i in 1..1000
5 loop
6 select count(*) into cnt from testtab;
7 end loop;
8 end;
9 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:03.19
SQL>
SQL> declare
2 cnt number;
3 begin
4 for i in 1..1000
5 loop
6 select max(rownum) into cnt from testtab;
7 end loop;
8 end;
9 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:15.87
SQL>
This shows that what makes the MAX() more expensive is just that - determining the MAX(). For each row, Oracle has to call its internal MAX() function with two values - the current max result and the new value. This function then returns the new max value. This overhead per row adds up to a significant overhead in execution time - making the MAX() approach 5x slower than the COUNT() approach. -
How to add a new column (Project Number) in the action items table under NPD Module?
There are two projects with same name and created by same person in NPD.
So when it is displayed in "Action Items" table, It looks similar.
To avoid this, I need one more column (Project Number) to be added in the "Action Items" table and " Strategic briefs and projects" table.
So, How to add a new column (Project Number) in the "Action Items" table and " Strategic briefs and projects" table under NPD Module?
Please do the needful.There is no out of the box configuration available to add columns to NPD action items. As always we welcome enhancement requests.
Thanks
Kelly -
ORA 01792 maximum number of columns in a table or view is 1000
Hello every1, I wish to register a large xmlschema doc, I am using the command
begin
dbms_xmlschema.registerschema(
schemaurl=>'xxxx',
schemadoc=>bfilename('XMLDIR','xxxxxx.xsd'),
csid=>nls_charset_id('AL32UTF8'));
end;
But the schema file exists 1000 col and it gives me the error msg of
ORA-01792: maximum number of columns in a table or view is 1000
is there anyway to solve the problems without edit the original schema document?
Thanks for your helpFirst create this package
create or replace package XDB_ANALYZE_XMLSCHEMA_10200
authid CURRENT_USER
as
function analyzeStorageModel(P_COMPLEX_TYPE_NAME VARCHAR2) return XMLTYPE;
function analyzeComplexType(COMPLEX_TYPE VARCHAR2) return XMLTYPE;
procedure renameCollectionTable (XMLTABLE varchar2, XPATH varchar2, COLLECTION_TABLE_PREFIX varchar2);
function printNestedTables(XML_TABLE varchar2) return XMLType;
function getComplexTypeElementList(P_SQLTYPE VARCHAR2, P_SQLSCHEMA VARCHAR2) return XDB.XDB$XMLTYPE_REF_LIST_T;
procedure scopeXMLReferences;
procedure indexXMLReferences(INDEX_NAME VARCHAR2);
function generateSchemaFromTable(P_TABLE_NAME varchar2, P_OWNER varchar2 default USER) return XMLTYPE;
function showSQLTypes(schemaFolder varchar2) return XMLType;
function generateCreateTableStatement(XML_TABLE_NAME varchar2, NEW_TABLE_NAME varchar2) return CLOB;
end XDB_ANALYZE_XMLSCHEMA_10200;
show errors
create or replace package body XDB_ANALYZE_XMLSCHEMA_10200
as
G_DEPTH_COUNT NUMBER(2) := 0;
TYPE BASETYPE_T is RECORD
SUBTYPE varchar2(128),
SUBTYPE_OWNER varchar2(32),
BASETYPE varchar2(128),
BASETYPE_OWNER varchar2(32)
TYPE BASETYPE_LIST_T IS TABLE OF BASETYPE_T;
BASETYPE_LIST BASETYPE_LIST_T := BASETYPE_LIST_T();
function findStorageModel(P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2, P_INCLUDE_SUBTYPES VARCHAR2 DEFAULT 'YES') return XMLType;
function getLocalAttributes(P_TYPE_NAME varchar2, P_TYPE_OWNER VARCHAR2) return XMLType;
function makeElement(P_NAME varchar2)
return xmltype
as
V_NAME varchar2(4000) := P_NAME;
begin
-- -- dbms_output.put_line('Processing : ' || P_NAME);
if (P_NAME LIKE '%$') then
V_NAME := SUBSTR(V_NAME,1,LENGTH(V_NAME) - 1);
end if;
if (P_NAME LIKE '%$%') then
V_NAME := REPLACE(V_NAME,'$','_0x22_');
end if;
return XMLTYPE( '<' || V_NAME || '/>');
end;
function getPathToRoot(SUBTYPE VARCHAR2, SUBTYPE_OWNER VARCHAR2)
return varchar2
as
TYPE_HIERARCHY varchar2(4000);
begin
SELECT sys_connect_by_path( OWNER || '.' || TYPE_NAME , '/')
INTO TYPE_HIERARCHY
FROM ALL_TYPES
WHERE TYPE_NAME = SUBTYPE
AND OWNER = SUBTYPE_OWNER
CONNECT BY SUPERTYPE_NAME = PRIOR TYPE_NAME
AND SUPERTYPE_OWNER = PRIOR OWNER
START WITH SUPERTYPE_NAME IS NULL
AND SUPERTYPE_OWNER IS NULL;
return TYPE_HIERARCHY;
end;
function expandSQLType(ATTR_NAME VARCHAR2, SUBTYPE VARCHAR2, SUBTYPE_OWNER VARCHAR2)
return XMLType
as
STORAGE_MODEL XMLTYPE;
ATTRIBUTES XMLTYPE;
EXTENDED_TYPE XMLTYPE;
ATTR_COUNT NUMBER := 0;
CURSOR FIND_EXTENDED_TYPES
is
select TYPE_NAME, OWNER
from ALL_TYPES
where SUPERTYPE_NAME = SUBTYPE
and SUPERTYPE_OWNER = SUBTYPE_OWNER;
begin
-- dbms_output.put_line('Processing SQLType : "' || SUBTYPE_OWNER || '.' || SUBTYPE || '".' );
STORAGE_MODEL := makeElement(ATTR_NAME);
select insertChildXML(STORAGE_MODEL,'/' || STORAGE_MODEL.getRootElement(),'@type',SUBTYPE)
into STORAGE_MODEL
from dual;
select insertChildXML(STORAGE_MODEL,'/' || STORAGE_MODEL.getRootElement(),'@typeOwner',SUBTYPE_OWNER)
into STORAGE_MODEL
from dual;
ATTRIBUTES := getLocalAttributes(SUBTYPE, SUBTYPE_OWNER);
ATTR_COUNT := ATTR_COUNT + ATTRIBUTES.extract('/' || ATTRIBUTES.getRootElement() || '/@columns').getNumberVal();
select appendChildXML(STORAGE_MODEL,'/' || STORAGE_MODEL.getRootElement(),ATTRIBUTES)
into STORAGE_MODEL
from DUAL;
for t in FIND_EXTENDED_TYPES loop
EXTENDED_TYPE := expandSQLType('ExtendedType',T.TYPE_NAME,T.OWNER);
ATTR_COUNT := ATTR_COUNT + EXTENDED_TYPE.extract('/' || EXTENDED_TYPE.getRootElement() || '/@columns').getNumberVal();
select appendChildXML(STORAGE_MODEL,'/' || STORAGE_MODEL.getRootElement(),EXTENDED_TYPE)
into STORAGE_MODEL
from DUAL;
end loop;
select insertChildXML(STORAGE_MODEL,'/' || STORAGE_MODEL.getRootElement(),'@columns',ATTR_COUNT)
into STORAGE_MODEL
from dual;
return STORAGE_MODEL;
end;
function getLocalAttributes(P_TYPE_NAME varchar2, P_TYPE_OWNER VARCHAR2)
return XMLType
as
V_ATTRIBUTE_COUNT NUMBER := 0;
V_TOTAL_ATTRIBUTES NUMBER := 0;
V_TEMP_RESULT NUMBER;
V_COLLECTION_TYPE varchar2(32);
V_COLLECTION_OWNER varchar2(32);
CURSOR FIND_CHILD_ATTRS
is
select ATTR_NAME, ATTR_TYPE_OWNER, ATTR_TYPE_NAME, INHERITED
from ALL_TYPE_ATTRS
where TYPE_NAME = P_TYPE_NAME
and OWNER = P_TYPE_OWNER
and INHERITED = 'NO'
order by ATTR_NO;
V_ATTR DBMS_XMLDOM.DOMATTR;
V_ATTRIBUTE_LIST XMLTYPE;
V_ATTRIBUTE_LIST_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ATTRIBUTE_LIST_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTRIBUTE XMLTYPE;
V_ATTRIBUTE_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ATTRIBUTE_ROOT DBMS_XMLDOM.DOMELEMENT;
V_TYPE_DEFINITION XMLTYPE;
V_TYPE_DEFINITION_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_TYPE_DEFINITION_ROOT DBMS_XMLDOM.DOMELEMENT;
begin
V_ATTRIBUTE_LIST := makeElement('Attributes');
V_ATTRIBUTE_LIST_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_ATTRIBUTE_LIST);
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_ATTRIBUTE_LIST_DOCUMENT);
for ATTR in FIND_CHILD_ATTRS loop
-- Finding Element / Attribute Name could be tricky. Use SQLName
V_ATTRIBUTE := makeElement(ATTR.ATTR_NAME);
V_ATTRIBUTE_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_ATTRIBUTE);
V_ATTRIBUTE_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_ATTRIBUTE_DOCUMENT);
begin
-- Check for Attributes based on collection types, With Nested Table storage each Collection will cost 2 columns.
select ELEM_TYPE_NAME, ELEM_TYPE_OWNER
into V_COLLECTION_TYPE, V_COLLECTION_OWNER
from ALL_COLL_TYPES
where TYPE_NAME = ATTR.ATTR_TYPE_NAME
and OWNER = ATTR.ATTR_TYPE_OWNER;
-- -- dbms_output.put_line('Adding "' || ATTR.ATTR_NAME || '". Collection of "' || ATTR.ATTR_TYPE_OWNER || '"."' || ATTR.ATTR_TYPE_NAME || '".');
-- Attribute is a Collection Type.
-- Collection will be managed as a NESTED TABLE
-- Each Collection cost 2 columns.
-- May want to count the number of columns in the NESTED_TABLE at a later date.
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLCollType');
DBMS_XMLDOM.SETVALUE(V_ATTR,ATTR.ATTR_TYPE_NAME);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLCollTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,ATTR.ATTR_TYPE_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLType');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_COLLECTION_TYPE);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_COLLECTION_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,2);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
exception
when no_data_found then
-- Attribute is not a collection type.
begin
-- Check for Attributes based on non-scalar types.
select 1
into V_TEMP_RESULT
from ALL_TYPES
where TYPE_NAME = ATTR.ATTR_TYPE_NAME
and OWNER = ATTR.ATTR_TYPE_OWNER;
-- Attribute is based on a non-scalar type. Find the Storage Model for this type.
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLType');
DBMS_XMLDOM.SETVALUE(V_ATTR,ATTR.ATTR_TYPE_NAME);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,ATTR.ATTR_TYPE_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_TYPE_DEFINITION := findStorageModel(ATTR.ATTR_TYPE_NAME, ATTR.ATTR_TYPE_OWNER, 'YES');
V_TYPE_DEFINITION_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_TYPE_DEFINITION);
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_TYPE_DEFINITION_DOCUMENT);
V_ATTRIBUTE_COUNT := DBMS_XMLDOM.GETATTRIBUTE(V_TYPE_DEFINITION_ROOT,'columns');
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_ATTRIBUTE_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT),TRUE));
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_ROOT),DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_TYPE_DEFINITION_DOCUMENT);
if (ATTR.ATTR_TYPE_NAME = 'XDB$ENUM_T' and ATTR.ATTR_TYPE_OWNER = 'XDB') then
-- The cost of a XDB$ENUM_T is 2 columns
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,2);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
else
-- The cost of a non scalar Type is the number of attributes plus one for Type and one for the TYPEID.
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_ATTRIBUTE_COUNT + 2);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
end if;
exception
when no_data_found then
-- Attribute is based on a scalar type
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'SQLType');
DBMS_XMLDOM.SETVALUE(V_ATTR,ATTR.ATTR_TYPE_NAME);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,1);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_ROOT,V_ATTR);
end;
end;
V_TOTAL_ATTRIBUTES := V_TOTAL_ATTRIBUTES + DBMS_XMLDOM.GETATTRIBUTE(V_ATTRIBUTE_ROOT,'columns');
V_ATTRIBUTE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_ATTRIBUTE_LIST_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_ROOT),TRUE));
V_ATTRIBUTE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_LIST_ROOT),DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_ATTRIBUTE_DOCUMENT);
if (V_TOTAL_ATTRIBUTES > 25000) then
exit;
end if;
end loop;
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_ATTRIBUTE_LIST_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_TOTAL_ATTRIBUTES);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ATTRIBUTE_LIST_ROOT,V_ATTR);
return V_ATTRIBUTE_LIST;
end;
function getSubTypes(P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2)
return XMLType
as
CURSOR FIND_SUBTYPES
is
select TYPE_NAME, OWNER
from ALL_TYPES
where SUPERTYPE_NAME = P_TYPE_NAME
and SUPERTYPE_OWNER = P_TYPE_OWNER;
CURSOR FIND_SUBTYPE_HEIRARCHY
is
select LEVEL, TYPE_NAME, OWNER
from ALL_TYPES
where TYPE_NAME <> P_TYPE_NAME
and OWNER <> P_TYPE_OWNER
connect by SUPERTYPE_NAME = PRIOR TYPE_NAME
and SUPERTYPE_OWNER = PRIOR OWNER
start with TYPE_NAME = P_TYPE_NAME
and OWNER = P_TYPE_OWNER;
V_SUBTYPE_LIST XMLType;
V_SUBTYPE_LIST_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_SUBTYPE_LIST_ROOT DBMS_XMLDOM.DOMELEMENT;
V_TYPE_DEFINITION XMLType;
V_TYPE_DEFINITION_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_TYPE_DEFINITION_ROOT DBMS_XMLDOM.DOMELEMENT;
V_SUBTYPE_DEFINITIONS XMLType;
V_SUBTYPE_DEFINITIONS_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_SUBTYPE_DEFINITIONS_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTRIBUTE_LIST XMLType;
V_ATTRIBUTE_LIST_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ATTRIBUTE_LIST_ROOT DBMS_XMLDOM.DOMELEMENT;
V_SUBTYPES_EXIST BOOLEAN := FALSE;
V_TOTAL_columns number;
V_ATTRIBUTE_COUNT number;
V_ATTR DBMS_XMLDOM.DOMATTR;
V_COMPLEX_TYPE VARCHAR2(256);
begin
V_SUBTYPE_LIST := makeElement('SubTypeDefinitions');
V_SUBTYPE_LIST_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_SUBTYPE_LIST);
V_SUBTYPE_LIST_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_SUBTYPE_LIST_DOCUMENT);
V_TOTAL_columns := 0;
for t in FIND_SUBTYPES() loop
V_SUBTYPES_EXIST := TRUE;
V_TYPE_DEFINITION := makeElement(t.TYPE_NAME);
V_TYPE_DEFINITION_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_TYPE_DEFINITION);
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_TYPE_DEFINITION_DOCUMENT);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_TYPE_DEFINITION_DOCUMENT,'SQLTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,t.OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_TYPE_DEFINITION_ROOT,V_ATTR);
begin
select x.XMLDATA.NAME
into V_COMPLEX_TYPE
from XDB.XDB$COMPLEX_TYPE x
where x.XMLDATA.SQLTYPE = t.TYPE_NAME
and x.XMLDATA.SQLSCHEMA = t.OWNER;
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_TYPE_DEFINITION_DOCUMENT,'type');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_COMPLEX_TYPE);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_TYPE_DEFINITION_ROOT,V_ATTR);
-- Consider adding Schema URL Attribute
exception
when no_data_found then
null;
when others then
raise;
end;
V_ATTRIBUTE_LIST := getLocalAttributes(t.TYPE_NAME, t.OWNER);
V_ATTRIBUTE_LIST_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_ATTRIBUTE_LIST);
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_ATTRIBUTE_LIST_DOCUMENT);
V_ATTRIBUTE_COUNT := DBMS_XMLDOM.GETATTRIBUTE(V_ATTRIBUTE_LIST_ROOT,'columns');
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_TYPE_DEFINITION_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_LIST_ROOT),TRUE));
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT),DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_LIST_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_ATTRIBUTE_LIST_DOCUMENT);
V_SUBTYPE_DEFINITIONS := getSubTypes(t.TYPE_NAME,t.OWNER);
if (V_SUBTYPE_DEFINITIONS is not NULL) then
V_SUBTYPE_DEFINITIONS_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_SUBTYPE_DEFINITIONS);
V_SUBTYPE_DEFINITIONS_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_SUBTYPE_DEFINITIONS_DOCUMENT);
V_ATTRIBUTE_COUNT := V_ATTRIBUTE_COUNT + DBMS_XMLDOM.GETATTRIBUTE(V_SUBTYPE_DEFINITIONS_ROOT,'columns');
V_SUBTYPE_DEFINITIONS_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_TYPE_DEFINITION_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_SUBTYPE_DEFINITIONS_ROOT),TRUE));
V_SUBTYPE_DEFINITIONS_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT),DBMS_XMLDOM.MAKENODE(V_SUBTYPE_DEFINITIONS_ROOT)));
end if;
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_TYPE_DEFINITION_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_ATTRIBUTE_COUNT);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_TYPE_DEFINITION_ROOT,V_ATTR);
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_SUBTYPE_LIST_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT),TRUE));
V_TYPE_DEFINITION_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_SUBTYPE_LIST_ROOT),DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION_ROOT)));
V_TOTAL_columns := V_TOTAL_columns + V_ATTRIBUTE_COUNT;
end loop;
if (V_SUBTYPES_EXIST) then
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_SUBTYPE_LIST_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_TOTAL_columns);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_SUBTYPE_LIST_ROOT,V_ATTR);
return V_SUBTYPE_LIST;
else
return NULL;
end if;
end;
function findSuperTypeModel(P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2)
return XMLType
as
begin
-- dbms_output.put_line('Processing Super Type : "' || P_TYPE_OWNER || '"."' || P_TYPE_NAME || '"');
return findStorageModel(P_TYPE_NAME, P_TYPE_OWNER,'NO');
end;
function getStorageModel(P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2, P_INCLUDE_SUBTYPES VARCHAR2 DEFAULT 'YES')
return XMLType
as
V_TYPE_DEFINITION XMLTYPE;
V_ATTRIBUTE_COUNT NUMBER := 0;
SUBTYPE_STORAGE_MODEL XMLTYPE;
V_SUPERTYPE_DEFINITION XMLTYPE;
V_SUPERTYPE_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_SUPERTYPE_ROOT DBMS_XMLDOM.DOMELEMENT;
V_SUBTYPE_DEFINITION XMLTYPE;
V_SUBTYPE_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_SUBTYPE_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTRIBUTE_LIST XMLTYPE;
V_ATTRIBUTE_LIST_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ATTRIBUTE_LIST_ROOT DBMS_XMLDOM.DOMELEMENT;
cursor FIND_SUPERTYPE_HEIRARCHY
is
select TYPE_NAME, OWNER
from ALL_TYPES
where TYPE_NAME <> P_TYPE_NAME
and OWNER <> P_TYPE_OWNER
connect by TYPE_NAME = PRIOR SUPERTYPE_NAME
and OWNER = PRIOR SUPERTYPE_OWNER
start with TYPE_NAME = P_TYPE_NAME
and OWNER = P_TYPE_OWNER
order by LEVEL;
V_COMPLEX_TYPE varchar2(256);
V_SUPERTYPE_NAME varchar2(256);
v_SUPERTYPE_OWNER varchar2(256);
V_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTR DBMS_XMLDOM.DOMATTR;
begin
-- dbms_output.put_line('Generating Storage Model for : "' || P_TYPE_OWNER || '"."' || P_TYPE_NAME || '"');
V_TYPE_DEFINITION := makeElement(P_TYPE_NAME);
V_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_TYPE_DEFINITION);
V_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_DOCUMENT);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'SQLTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,P_TYPE_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
begin
select x.XMLDATA.NAME
into V_COMPLEX_TYPE
from XDB.XDB$COMPLEX_TYPE x
where x.XMLDATA.SQLTYPE = P_TYPE_NAME
and x.XMLDATA.SQLSCHEMA = P_TYPE_OWNER;
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'type');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_COMPLEX_TYPE);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
-- Consider adding Schema URL Attribute
exception
when no_data_found then
null;
when others then
raise;
end;
select SUPERTYPE_NAME, SUPERTYPE_OWNER
into V_SUPERTYPE_NAME, V_SUPERTYPE_OWNER
from ALL_TYPES
where TYPE_NAME = P_TYPE_NAME
and OWNER = P_TYPE_OWNER;
-- Process SuperType.
if (V_SUPERTYPE_NAME is not null) then
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'SQLParentType');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_SUPERTYPE_NAME);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'SQLParentTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_SUPERTYPE_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
-- Find the Definition for the super type. Do not include the definition of it's subtypes.
V_SUPERTYPE_DEFINITION := findSuperTypeModel(V_SUPERTYPE_NAME, V_SUPERTYPE_OWNER);
-- -- dbms_output.put_line(dbms_lob.substr(V_SUPERTYPE_DEFINITION.getClobVal(),1000,1));
V_SUPERTYPE_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_SUPERTYPE_DEFINITION);
V_SUPERTYPE_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_SUPERTYPE_DOCUMENT);
V_ATTRIBUTE_COUNT := V_ATTRIBUTE_COUNT + DBMS_XMLDOM.GETATTRIBUTE(V_SUPERTYPE_ROOT,'columns');
V_SUPERTYPE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_SUPERTYPE_ROOT),TRUE));
V_SUPERTYPE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ROOT),DBMS_XMLDOM.MAKENODE(V_SUPERTYPE_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_SUPERTYPE_DOCUMENT);
end if;
-- Process Attributes defined directly by the Type.
V_ATTRIBUTE_LIST := getLocalAttributes(P_TYPE_NAME, P_TYPE_OWNER);
V_ATTRIBUTE_LIST_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_ATTRIBUTE_LIST);
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_ATTRIBUTE_LIST_DOCUMENT);
V_ATTRIBUTE_COUNT := V_ATTRIBUTE_COUNT + DBMS_XMLDOM.GETATTRIBUTE(V_ATTRIBUTE_LIST_ROOT,'columns');
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_LIST_ROOT),TRUE));
V_ATTRIBUTE_LIST_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ROOT),DBMS_XMLDOM.MAKENODE(V_ATTRIBUTE_LIST_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_ATTRIBUTE_LIST_DOCUMENT);
if (P_INCLUDE_SUBTYPES = 'YES') then
-- Process any Sub-Types...
V_SUBTYPE_DEFINITION := getSubTypes(P_TYPE_NAME, P_TYPE_OWNER);
if (V_SUBTYPE_DEFINITION is not null) then
V_SUBTYPE_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_SUBTYPE_DEFINITION);
V_SUBTYPE_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_SUBTYPE_DOCUMENT);
V_ATTRIBUTE_COUNT := V_ATTRIBUTE_COUNT + DBMS_XMLDOM.GETATTRIBUTE(V_SUBTYPE_ROOT,'columns');
V_SUBTYPE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_SUBTYPE_ROOT),TRUE));
V_SUBTYPE_ROOT := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ROOT),DBMS_XMLDOM.MAKENODE(V_SUBTYPE_ROOT)));
DBMS_XMLDOM.FREEDOCUMENT(V_SUBTYPE_DOCUMENT);
end if;
end if;
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,V_ATTRIBUTE_COUNT);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
-- Cache the type definition.
-- dbms_output.put_line('Cached Storage Model for "' || P_TYPE_OWNER || '.' || P_TYPE_NAME || '".');
insert into XDBPM.XDBPM_STORAGE_MODEL_CACHE (TYPE_NAME, TYPE_OWNER, EXTENDED_DEFINITION, STORAGE_MODEL) VALUES (P_TYPE_NAME, P_TYPE_OWNER, P_INCLUDE_SUBTYPES, V_TYPE_DEFINITION);
return V_TYPE_DEFINITION;
end;
function findStorageModel(P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2, P_INCLUDE_SUBTYPES VARCHAR2 DEFAULT 'YES')
-- Find the Storage Model for the Base Type.
-- If the type is derived from another type we need the storage model of the Base Type
-- As storage models are calculated they are cached in the global temporary table XDBPM_STORAGE_MODEL_CACHE. This makes
-- the process much more efficient. A global temporary table is used to minimize memory usage.
return XMLType
as
V_STORAGE_MODEL XMLType;
V_STORAGE_MODEL_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_STORAGE_MODEL_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTRIBUTE_COUNT VARCHAR2(10);
begin
dbms_output.put_line('findStorageModel(' || G_DEPTH_COUNT || ') : Processing "' || P_TYPE_OWNER || '"."' || P_TYPE_NAME || '".' );
begin
SELECT STORAGE_MODEL
into V_STORAGE_MODEL
from XDBPM.XDBPM_STORAGE_MODEL_CACHE
where TYPE_NAME = P_TYPE_NAME
and TYPE_OWNER = P_TYPE_OWNER
and EXTENDED_DEFINITION = P_INCLUDE_SUBTYPES;
-- dbms_output.put_line('Resolved Storage Model from cache.');
exception
when no_data_found then
G_DEPTH_COUNT := G_DEPTH_COUNT + 1;
V_STORAGE_MODEL := getStorageModel(P_TYPE_NAME,P_TYPE_OWNER, P_INCLUDE_SUBTYPES);
G_DEPTH_COUNT := G_DEPTH_COUNT - 1;
when others then
raise;
end;
V_STORAGE_MODEL_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_STORAGE_MODEL);
V_STORAGE_MODEL_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_STORAGE_MODEL_DOCUMENT);
V_ATTRIBUTE_COUNT := DBMS_XMLDOM.GETATTRIBUTE(V_STORAGE_MODEL_ROOT,'columns');
dbms_output.put_line('findStorageModel : Attribute Count for "' || P_TYPE_OWNER || '"."' || P_TYPE_NAME || '" = ' || V_ATTRIBUTE_COUNT || '.' );
return V_STORAGE_MODEL;
end;
function analyzeStorageModel(P_COMPLEX_TYPE_NAME VARCHAR2, P_TYPE_NAME VARCHAR2, P_TYPE_OWNER VARCHAR2)
-- Generate a map showing the number of columns required to persist an instance of the SQL type.
return XMLType
as
V_STORAGE_MODEL XMLTYPE;
V_COUNT NUMBER := 0;
V_DOCUMENT DBMS_XMLDOM.DOMDOCUMENT;
V_ROOT DBMS_XMLDOM.DOMELEMENT;
V_ATTR DBMS_XMLDOM.DOMATTR;
V_MODEL DBMS_XMLDOM.DOMELEMENT;
V_TYPE_DEFINITION DBMS_XMLDOM.DOMELEMENT;
begin
V_STORAGE_MODEL := makeElement(P_COMPLEX_TYPE_NAME);
V_DOCUMENT := DBMS_XMLDOM.NEWDOMDOCUMENT(V_STORAGE_MODEL);
V_ROOT := DBMS_XMLDOM.GETDOCUMENTELEMENT(V_DOCUMENT);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'SQLType');
DBMS_XMLDOM.SETVALUE(V_ATTR,P_TYPE_NAME);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'SQLTypeOwner');
DBMS_XMLDOM.SETVALUE(V_ATTR,P_TYPE_OWNER);
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
V_TYPE_DEFINITION := DBMS_XMLDOM.GETDOCUMENTELEMENT(DBMS_XMLDOM.NEWDOMDOCUMENT(findStorageModel(P_TYPE_NAME, P_TYPE_OWNER, 'YES')));
V_TYPE_DEFINITION := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.IMPORTNODE(V_DOCUMENT,DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION),TRUE));
V_TYPE_DEFINITION := DBMS_XMLDOM.MAKEELEMENT(DBMS_XMLDOM.APPENDCHILD(DBMS_XMLDOM.MAKENODE(V_ROOT),DBMS_XMLDOM.MAKENODE(V_TYPE_DEFINITION)));
V_ATTR := DBMS_XMLDOM.CREATEATTRIBUTE(V_DOCUMENT,'columns');
DBMS_XMLDOM.SETVALUE(V_ATTR,DBMS_XMLDOM.GETATTRIBUTE(V_TYPE_DEFINITION,'columns'));
V_ATTR := DBMS_XMLDOM.SETATTRIBUTENODE(V_ROOT,V_ATTR);
return V_STORAGE_MODEL;
end;
function analyzeStorageModel(P_COMPLEX_TYPE_NAME VARCHAR2)
return XMLTYPE
-- Generate a map showing the number of columns required to persist an instance of the complex type.
as
pragma autonomous_transaction;
V_SQLTYPE VARCHAR2(128);
V_SQLSCHEMA VARCHAR2(32);
V_RESULT XMLType;
begin
G_DEPTH_COUNT := 0;
select ct.XMLDATA.SQLTYPE, ct.XMLDATA.SQLSCHEMA
into V_SQLTYPE, V_SQLSCHEMA
from XDB.XDB$COMPLEX_TYPE ct, XDB.XDB$SCHEMA s
where ct.XMLDATA.NAME = P_COMPLEX_TYPE_NAME
and ref(s) = ct.XMLDATA.PARENT_SCHEMA
and s.XMLDATA.SCHEMA_OWNER = USER;
delete from XDBPM.XDBPM_STORAGE_MODEL_CACHE;
-- delete from XDBPM.XDBPM_STORAGE_MODEL;
V_RESULT := analyzeStorageModel(P_COMPLEX_TYPE_NAME,V_SQLTYPE,V_SQLSCHEMA);
COMMIT;
return V_RESULT;
exception
when no_data_found then
-- dbms_output.put_line('Unable to find SQLType mapping for complexType : "' || USER || '"."' || P_COMPLEX_TYPE_NAME || '".' );
return null;
when others then
raise;
end;
function analyzeSQLType(ATTR_NAME VARCHAR2, TARGET_TYPE_NAME VARCHAR2, TARGET_TYPE_OWNER VARCHAR2)
return XMLType
as
ROOT_NODE_NAME VARCHAR2(128);
ATTR_DETAIL XMLTYPE;
XPATH_EXPRESSION VARCHAR2(129);
CURSOR FIND_CHILD_ATTRS is
select ATTR_NAME, ATTR_TYPE_OWNER, ATTR_TYPE_NAME, INHERITED
from ALL_TYPE_ATTRS
where OWNER = TARGET_TYPE_OWNER
and TYPE_NAME = TARGET_TYPE_NAME
order by ATTR_NO;
CHILD_ATTR XMLTYPE;
ATTR_COUNT NUMBER := 0;
TEMP number;
COLLECTION_TYPE_NAME varchar2(256);
COLLECTION_TYPE_OWNER varchar2(256);
begin
-- -- dbms_output.put_line('Processing Attribute ' || ATTR_NAME || ' of ' || TARGET_TYPE_OWNER || '.' || TARGET_TYPE_NAME );
ATTR_DETAIL := makeElement(ATTR_NAME);
XPATH_EXPRESSION := '/' || ATTR_DETAIL.GETROOTELEMENT();
for ATTR in FIND_CHILD_ATTRS loop
begin
select ELEM_TYPE_NAME, ELEM_TYPE_OWNER
into COLLECTION_TYPE_NAME, COLLECTION_TYPE_OWNER
from ALL_COLL_TYPES
where TYPE_NAME = ATTR.ATTR_TYPE_NAME
and OWNER = ATTR.ATTR_TYPE_OWNER;
CHILD_ATTR := analyzeSQLType(ATTR.ATTR_NAME, COLLECTION_TYPE_NAME, COLLECTION_TYPE_OWNER );
ATTR_COUNT := ATTR_COUNT + CHILD_ATTR.extract('/' || CHILD_ATTR.GETROOTELEMENT() || '/@sqlAttrs').getNumberVal();
select appendChildXML(ATTR_DETAIL,XPATH_EXPRESSION,CHILD_ATTR)
into ATTR_DETAIL
from DUAL;
exception
when no_data_found then
begin
select 1
into TEMP
from ALL_TYPES
where TYPE_NAME = ATTR.ATTR_TYPE_NAME
and OWNER = ATTR.ATTR_TYPE_OWNER;
CHILD_ATTR := analyzeSQLType(ATTR.ATTR_NAME, ATTR.ATTR_TYPE_NAME, ATTR.ATTR_TYPE_OWNER );
ATTR_COUNT := ATTR_COUNT + CHILD_ATTR.extract('/' || CHILD_ATTR.GETROOTELEMENT() || '/@sqlAttrs').getNumberVal();
select appendChildXML(ATTR_DETAIL,XPATH_EXPRESSION,CHILD_ATTR)
into ATTR_DETAIL
from DUAL;
exception
when no_data_found then
ATTR_COUNT := ATTR_COUNT + 1;
end;
end;
end loop;
select insertChildXML(ATTR_DETAIL,XPATH_EXPRESSION,'@sqlAttrs',ATTR_COUNT)
into ATTR_DETAIL
from dual;
return ATTR_DETAIL;
end;
function analyzeComplexType(COMPLEX_TYPE VARCHAR2)
return XMLType
as
RESULT xmltype;
SQLTYPE varchar2(128);
SQLTYPE_OWNER varchar2(32);
begin
select SQLTYPE, SQLTYPE_OWNER
into SQLTYPE, SQLTYPE_OWNER
from USER_XML_SCHEMAS,
xmlTable
xmlnamespaces
'http://www.w3.org/2001/XMLSchema' as "xsd",
'http://xmlns.oracle.com/xdb' as "xdb"
'/xsd:schema/xsd:complexType'
passing Schema
columns
COMPLEX_TYPE_NAME varchar2(4000) path '@name',
SQLTYPE varchar2(128) path '@xdb:SQLType',
SQLTYPE_OWNER varchar2(32) path '@xdb:SQLSchema'
where COMPLEX_TYPE_NAME = COMPLEX_TYPE;
result := analyzeSQLType(COMPLEX_TYPE,SQLTYPE,SQLTYPE_OWNER);
select insertChildXML(RESULT,'/' || COMPLEX_TYPE,'@SQLType',SQLTYPE)
into result
from dual;
return result;
end;
function showSQLTypes(schemaFolder varchar2) return XMLType
is
xmlSchema XMLTYPE;
begin
select xmlElement
"TypeList",
xmlAgg
xmlElement
"Schema",
xmlElement
"ResourceName",
extractValue(res,'/Resource/DisplayName')
xmlElement
"complexTypes",
select xmlAgg
xmlElement
"complexType",
xmlElement
"name",
extractValue(value(XML),'/xsd:complexType/@name',XDB_NAMESPACES.XDBSCHEMA_PREFIXES)
xmlElement
"SQLType",
extractValue(value(XML),'/xsd:complexType/@xdb:SQLType',XDB_NAMESPACES.XDBSCHEMA_PREFIXES)
from table
xmlsequence
extract
xdburitype(p.path).getXML(),
'/xsd:schema/xsd:complexType',
XDB_NAMESPACES.XDBSCHEMA_PREFIXES
) xml
-- order by extractValue(value(XML),'/xsd:complexType/@name',XDB_NAMESPACES.XDBSCHEMA_PREFIXES)
).extract('/*')
into xmlSchema
from path_view p
where under_path(res,schemaFolder) = 1
order by extractValue(res,'/Resource/DisplayName');
return xmlSchema;
end;
procedure renameCollectionTable (XMLTABLE varchar2, XPATH varchar2, COLLECTION_TABLE_PREFIX varchar2)
as
SYSTEM_GENERATED_NAME varchar2(256);
COLLECTION_TABLE_NAME varchar2(256);
CLUSTERED_INDEX_NAME varchar2(256);
PARENT_INDEX_NAME varchar2(256);
RENAME_STATEMENT varchar2(4000);
begin
COLLECTION_TABLE_NAME := COLLECTION_TABLE_PREFIX || '_TABLE';
CLUSTERED_INDEX_NAME := COLLECTION_TABLE_PREFIX || '_DATA';
PARENT_INDEX_NAME := COLLECTION_TABLE_PREFIX || '_LIST';
select TABLE_NAME
into SYSTEM_GENERATED_NAME
from ALL_NESTED_TABLES
where PARENT_TABLE_NAME = XMLTABLE
and PARENT_TABLE_COLUMN = XPATH
and OWNER = USER;
RENAME_STATEMENT := 'alter table ' || USER || '."' || SYSTEM_GENERATED_NAME || '" rename to "' ||COLLECTION_TABLE_NAME || '"';
-- -- dbms_output.put_line(RENAME_STATEMENT);
execute immediate RENAME_STATEMENT;
begin
select INDEX_NAME
into SYSTEM_GENERATED_NAME
from ALL_INDEXES
where TABLE_NAME = COLLECTION_TABLE_NAME
and INDEX_TYPE = 'IOT - TOP'
and OWNER = USER;
RENAME_STATEMENT := 'alter index ' || USER || '."' || SYSTEM_GENERATED_NAME || '" rename to "' || CLUSTERED_INDEX_NAME || '"';
-- -- dbms_output.put_line(RENAME_STATEMENT);
execute immediate RENAME_STATEMENT;
exception
when NO_DATA_FOUND then
null;
end;
begin
select INDEX_NAME
into SYSTEM_GENERATED_NAME
from ALL_IND_columns
where COLUMN_NAME = XPATH
and TABLE_NAME = XMLTABLE
and TABLE_OWNER = USER;
RENAME_STATEMENT := 'alter index ' || USER || '."' || SYSTEM_GENERATED_NAME || '" rename to "' || PARENT_INDEX_NAME || '"';
-- -- dbms_output.put_line(RENAME_STATEMENT);
execute immediate RENAME_STATEMENT;
exception
when NO_DATA_FOUND then
null;
end;
end;
function processNestedTable(currentLevel in out number, currentNode in out XMLType, query SYS_REFCURSOR)
return XMLType
is
thisLevel number;
thisNode xmlType;
result xmlType;
begin
thisLevel := currentLevel;
thisNode := currentNode;
fetch query into currentLevel, currentNode;
if (query%NOTFOUND) then
currentLevel := -1;
end if;
while (currentLevel >= thisLevel) loop
-- Next Node is a decendant of sibling of this Node.
if (currentLevel > thisLevel) then
-- Next Node is a decendant of this Node.
result := processNestedTable(currentLevel, currentNode, query);
select xmlElement
"Collection",
extract(thisNode,'/Collection/*'),
xmlElement
"NestedCollections",
result
into thisNode
from dual;
else
-- Next node is a sibling of this Node.
result := processNestedTable(currentLevel, currentNode, query);
select xmlconcat(thisNode,result) into thisNode from dual;
end if;
end loop;
-- Next Node is a sibling of some ancestor of this node.
return thisNode;
end;
function printNestedTables(XML_TABLE varchar2)
return XMLType
is
query SYS_REFCURSOR;
result XMLType;
rootLevel number := 0;
rootNode xmlType;
begin
open query for
select level, xmlElement
"Collection",
xmlElement
"CollectionId",
PARENT_TABLE_COLUMN
) as XML
from USER_NESTED_TABLES
connect by PRIOR TABLE_NAME = PARENT_TABLE_NAME
start with PARENT_TABLE_NAME = XML_TABLE;
fetch query into rootLevel, rootNode;
result := processNestedTable(rootLevel, rootNode, query);
select xmlElement
"NestedTableStructure",
result
into result
from dual;
return result;
end;
function generateSchemaFromTable(P_TABLE_NAME varchar2, P_OWNER varchar2 default USER)
return XMLTYPE
as
xmlSchema XMLTYPE;
begin
select xmlElement
"xsd:schema",
xmlAttributes
'http://www.w3.org/2001/XMLSchema' as "xmlns:xsd",
'http://xmlns.oracle.com/xdb' as "xmlns:xdb"
xmlElement
"xsd:element",
xmlAttributes
'ROWSET' as "name",
'rowset' as "type"
xmlElement
"xsd:complexType",
xmlAttributes
'rowset' as "name"
xmlElement
"xsd:sequence",
xmlElement
"xsd:element",
xmlAttributes
'ROW' as "name",
table_name || '_T' as "type",
'unbounded' as "maxOccurs"
xmlElement
"xsd:complexType",
xmlAttributes
table_name || '_T' as "name"
xmlElement
"xsd:sequence",
xmlAgg(ELEMENT order by INTERNAL_COLUMN_ID)
into xmlSchema
from (select TABLE_NAME, INTERNAL_COLUMN_ID,
case
when DATA_TYPE in ('VARCHAR2','CHAR') then
xmlElement
"xsd:element",
xmlattributes
column_name as "name",
decode(NULLABLE, 'Y', 0, 1) as "minOccurs",
column_name as "xdb:SQLName",
DATA_TYPE as "xdb:SQLType"
xmlElement
"xsd:simpleType",
xmlElement
"xsd:restriction",
xmlAttributes
'xsd:string' as "base"
xmlElement
"xsd:maxLength",
xmlAttributes
DATA_LENGTH as "value"
when DATA_TYPE = 'NUMBER' then
xmlElement
"xsd:element",
xmlattributes
column_name as "name",
decode(NULLABLE, 'Y', 0, 1) as "minOccurs",
column_name as "xdb:SQLName",
DATA_TYPE as "xdb:SQLType"
xmlElement
"xsd:simpleType",
xmlElement
"xsd:restriction",
xmlAttributes
decode(DATA_SCALE, 0, 'xsd:integer', 'xsd:double') as "base"
xmlElement
"xsd:totalDigits",
xmlAttributes
DATA_PRECISION as "value"
when DATA_TYPE = 'DATE' then
xmlElement
"xsd:element",
xmlattributes
column_name as "name",
decode(NULLABLE, 'Y', 0, 1) as "minOccurs",
'xsd:date' as "type",
column_name as "xdb:SQLName",
DATA_TYPE as "xdb:SQLType"
when DATA_TYPE like 'TIMESTAMP%WITH TIME ZONE' then
xmlElement
"xsd:element",
xmlattributes
column_name as "name",
decode(NULLABLE, 'Y', 0, 1) as "minOccurs",
'xsd:dateTime' as "type",
column_name as "xdb:SQLName",
DATA_TYPE as "xdb:SQLType"
else
xmlElement
"xsd:element",
xmlattributes
column_name as "name",
decode(NULLABLE, 'Y', 0, 1) as "minOccurs",
'xsd:anySimpleType' as "type",
column_name as "xdb:SQLName",
DATA_TYPE as "xdb:SQLType"
end ELEMENT
from all_tab_cols c
where c.TABLE_NAME = P_TABLE_NAME
and c.OWNER = P_OWNER
group by TABLE_NAME;
return xmlSchema;
end;
function appendElementList(V_ELEMENT_LIST IN OUT XDB.XDB$XMLTYPE_REF_LIST_T, V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T) return XDB.XDB$XMLTYPE_REF_LIST_T;
function expandModel(P_MODEL XDB.XDB$MODEL_T) return XDB.XDB$XMLTYPE_REF_LIST_T;
function expandChoiceList(P_CHOICE_LIST XDB.XDB$XMLTYPE_REF_LIST_T) return XDB.XDB$XMLTYPE_REF_LIST_T;
function expandSequenceList(P_SEQUENCE_LIST XDB.XDB$XMLTYPE_REF_LIST_T) return XDB.XDB$XMLTYPE_REF_LIST_T;
function expandGroupList(P_GROUP_LIST XDB.XDB$XMLTYPE_REF_LIST_T) return XDB.XDB$XMLTYPE_REF_LIST_T;
function appendElementList(V_ELEMENT_LIST IN OUT XDB.XDB$XMLTYPE_REF_LIST_T, V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
begin
SELECT CAST
SET
CAST(V_ELEMENT_LIST as XDBPM.XMLTYPE_REF_TABLE_T)
MULTISET UNION
CAST(V_CHILD_ELEMENT_LIST as XDBPM.XMLTYPE_REF_TABLE_T)
as XDB.XDB$XMLTYPE_REF_LIST_T
into V_ELEMENT_LIST
from DUAL;
return V_ELEMENT_LIST;
end;
function expandModel(P_MODEL XDB.XDB$MODEL_T)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
V_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
begin
V_ELEMENT_LIST := XDB.XDB$XMLTYPE_REF_LIST_T();
if P_MODEL.ELEMENTS is not null then
V_ELEMENT_LIST := P_MODEL.ELEMENTS;
end if;
if (P_MODEL.CHOICE_KIDS is not NULL) then
V_CHILD_ELEMENT_LIST := expandChoiceList(P_MODEL.CHOICE_KIDS);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end if;
if (P_MODEL.SEQUENCE_KIDS is not NULL) then
V_CHILD_ELEMENT_LIST := expandSequenceList(P_MODEL.SEQUENCE_KIDS);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end if;
-- Process ANYS
if (P_MODEL.GROUPS is not NULL) then
V_CHILD_ELEMENT_LIST := expandGroupList(P_MODEL.GROUPS);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end if;
return V_ELEMENT_LIST;
end;
function expandChoiceList(P_CHOICE_LIST XDB.XDB$XMLTYPE_REF_LIST_T)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
V_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
cursor getChoices is
select c.XMLDATA MODEL
from XDB.XDB$CHOICE_MODEL c, TABLE(P_CHOICE_LIST) cl
where ref(c) = value(cl);
begin
V_ELEMENT_LIST := XDB.XDB$XMLTYPE_REF_LIST_T();
for c in getChoices loop
V_CHILD_ELEMENT_LIST := expandModel(c.MODEL);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end loop;
return V_ELEMENT_LIST;
end;
function expandSequenceList(P_SEQUENCE_LIST XDB.XDB$XMLTYPE_REF_LIST_T)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
V_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
cursor getSequences is
select s.XMLDATA MODEL
from XDB.XDB$SEQUENCE_MODEL s, TABLE(P_SEQUENCE_LIST) sl
where ref(s) = value(sl);
begin
V_ELEMENT_LIST := XDB.XDB$XMLTYPE_REF_LIST_T();
for s in getSequences loop
V_CHILD_ELEMENT_LIST := expandModel(s.MODEL);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end loop;
return V_ELEMENT_LIST;
end;
function expandGroupList(P_GROUP_LIST XDB.XDB$XMLTYPE_REF_LIST_T)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
V_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T;
V_CHILD_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T; V_MODEL XDB.XDB$MODEL_T;
cursor getGroups is
SELECT CASE
-- Return The MODEL Definition for the CHOICE, ALL or SEQUENCE
WHEN gd.XMLDATA.ALL_KID is not NULL
THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = gd.XMLDATA.ALL_KID)
WHEN gd.XMLDATA.SEQUENCE_KID is not NULL
THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = gd.XMLDATA.SEQUENCE_KID)
WHEN gd.XMLDATA.CHOICE_KID is not NULL
THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = gd.XMLDATA.CHOICE_KID)
END MODEL
FROM XDB.XDB$GROUP_DEF gd, XDB.XDB$GROUP_REF gr, TABLE(P_GROUP_LIST) gl
WHERE ref(gd) = gr.XMLDATA.GROUPREF_REF
and ref(gr) = value(gl);
begin
V_ELEMENT_LIST := XDB.XDB$XMLTYPE_REF_LIST_T();
for g in getGroups loop
V_CHILD_ELEMENT_LIST := expandModel(g.MODEL);
V_ELEMENT_LIST := appendElementList(V_ELEMENT_LIST,V_CHILD_ELEMENT_LIST);
end loop;
return V_ELEMENT_LIST;
end;
function getComplexTypeElementList(P_COMPLEX_TYPE_REF REF XMLTYPE)
return XDB.XDB$XMLTYPE_REF_LIST_T
as
V_MODEL XDB.XDB$MODEL_T;
V_BASE_TYPE REF XMLTYPE;
V_ELEMENT_LIST XDB.XDB$XMLTYPE_REF_LIST_T := XDB.XDB$XMLTYPE_REF_LIST_T();
begin
SELECT ct.XMLDATA.BASE_TYPE,
CASE
-- Return The MODEL Definition for the CHOICE, ALL or SEQUENCE
WHEN ct.XMLDATA.ALL_KID is not NULL
THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = ct.XMLDATA.ALL_KID)
WHEN ct.XMLDATA.SEQUENCE_KID is not NULL
THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = ct.XMLDATA.SEQUENCE_KID)
WHEN ct.XMLDATA.CHOICE_KID is not NULL
THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = ct.XMLDATA.CHOICE_KID)
WHEN ct.XMLDATA.GROUP_KID is not NULL
-- COMPLEXTYPE is based on a GROUP.
THEN (
-- RETURN The CHOICE, ALL or SEQUENCE for GROUP
SELECT CASE
WHEN gd.XMLDATA.ALL_KID is not NULL
THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = gd.XMLDATA.ALL_KID)
WHEN gd.XMLDATA.SEQUENCE_KID is not NULL
THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = gd.XMLDATA.SEQUENCE_KID)
WHEN gd.XMLDATA.CHOICE_KID is not NULL
THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = gd.XMLDATA.CHOICE_KID)
END
FROM XDB.XDB$GROUP_DEF gd, xdb.xdb$GROUP_REF gr
WHERE ref(gd) = gr.XMLDATA.GROUPREF_REF
and ref(gr) = ct.XMLDATA.GROUP_KID
-- WHEN ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.ALL_KID is not NULL
-- THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.ALL_KID)
-- WHEN ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.SEQUENCE_KID is not NULL
-- THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.SEQUENCE_KID)
-- WHEN ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.CHOICE_KID is not NULL
-- THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.CHOICE_KID)
-- WHEN ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.GROUP_KID is not NULL
-- -- COMPLEXTYPE is based on a GROUP.
-- THEN (
-- -- RETURN The CHOICE, ALL or SEQUENCE for GROUP
-- SELECT CASE
-- WHEN gd.XMLDATA.ALL_KID is not NULL
-- THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = gd.XMLDATA.ALL_KID)
-- WHEN gd.XMLDATA.SEQUENCE_KID is not NULL
-- THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = gd.XMLDATA.SEQUENCE_KID)
-- WHEN gd.XMLDATA.CHOICE_KID is not NULL
-- THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = gd.XMLDATA.CHOICE_KID)
-- END
-- FROM XDB.XDB$GROUP_DEF gd, xdb.xdb$GROUP_REF gr
-- WHERE ref(gd) = gr.XMLDATA.GROUPREF_REF
-- and ref(gr) = ct.XMLDATA.COMPLEXCONTENT.RESTRICTION.GROUP_KID
WHEN ct.XMLDATA.COMPLEXCONTENT.EXTENSION.ALL_KID is not NULL
THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = ct.XMLDATA.COMPLEXCONTENT.EXTENSION.ALL_KID)
WHEN ct.XMLDATA.COMPLEXCONTENT.EXTENSION.SEQUENCE_KID is not NULL
THEN ( SELECT s.XMLDATA from XDB.XDB$SEQUENCE_MODEL s where ref(s) = ct.XMLDATA.COMPLEXCONTENT.EXTENSION.SEQUENCE_KID)
WHEN ct.XMLDATA.COMPLEXCONTENT.EXTENSION.CHOICE_KID is not NULL
THEN ( SELECT c.XMLDATA from XDB.XDB$CHOICE_MODEL c where ref(c) = ct.XMLDATA.COMPLEXCONTENT.EXTENSION.CHOICE_KID)
WHEN ct.XMLDATA.COMPLEXCONTENT.EXTENSION.GROUP_KID is not NULL
-- COMPLEXTYPE is based on a GROUP.
THEN (
-- RETURN The CHOICE, ALL or SEQUENCE for GROUP
SELECT CASE
WHEN gd.XMLDATA.ALL_KID is not NULL
THEN ( SELECT a.XMLDATA from XDB.XDB$ALL_MODEL a where ref(a) = gd.XMLDATA.ALL_KID)
Maybe you are looking for
-
Recently when I open any apps the pages are too big for the screen. They shrink when pinched but immediately become bigger again. It's very difficult to scroll too. The keypad has become very sticky. Missing letters and spaces when I type and needing
-
What are MD_ tables in Oracle 12c database? What is their purpose?
I just set up an Oracle 12c database with the purpose of migrating an existing Oracle 11.2.0.2 database. Our application developers are a bit confused when it comes to the schemas suddenly having MD_ tables they did not create. Any help is apprecia
-
How to recover a Lightroom 3 to 4 Upgrade?
I bought Lightroom 3 on CD and installed that in my new system. But I cannot find my hard copy of the Lightroom 4 upgrade that I purchased, during 4's reign. Since my current Lightroom catalog is for 4, I want to upgrade the software for this new bui
-
Put html tag in xml genreted with strings panel
Hello, I created an multilanguage application with the "strings "panel. My customer need to put some words in italic inside the dynamic textfield. So I used <i> tag or cdata tag insied the xml, but nothing works, even if I put the textfield in "html"
-
W32time source showing as Local CMOS clock
I have 3 virtual servers, all on different hosts, which are currently showing the wrong time. All other machines on the Domain get their time from the Domain Controller. I have only been making changes on 1 server to ensure that this works. Originall