I would like to partition a table using a function over a column, due to I don't want to create a new column. My table Example has a column DATE_VARCHAR (format 'YYYY-MM-DD') and I would like to partition it given the month of the date, but I have some problems.
I can't add a column in the new structure (client requirements), so if I want to do the partitioning using substring function over DATE_VARCHAR, I get a syntax error:
CREATE TABLE PRUEBA( DATE_VARCHAR VARCHAR2(10), SOME_COLUMNS VARCHAR(50) ) PARTITION BY LIST (SUBSTR(DATE_VARCHAR,6,2)) (PARTITION p1 VALUES ('01','05','09'), PARTITION p2 VALUES ('02','06','10'), PARTITION p3 VALUES ('03','07','11'), PARTITION p4 VALUES ('04','08','12'));
Due to it expects an identifier column (column name), in spite of I get the following error: ORA-00907 missing right parenthesis .
If I create a column with the month value:
CREATE TABLE Example( DATE_VARCHAR VARCHAR2(10), SOME_COLUMNS VARCHAR(50), MONTH VARCHAR2(2) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL ) PARTITION BY LIST (MONTH) (PARTITION p1 VALUES ('01','05','09'), PARTITION p2 VALUES ('02','06','10'), PARTITION p3 VALUES ('03','07','11'), PARTITION p4 VALUES ('04','08','12'));
I get the following error: ORA-12899 value too large for column %s (actual: %s, maximum: %s) , due to the new column is only length 2 (and the source column is length 10); in spite of I'm doing a substring of length 2.
The only way to do this, is the 3? Exists another way to solve this?
Edit: If I do the next, it works for me:
CREATE TABLE Example(
DATE_VARCHAR VARCHAR2(10),
SOME_COLUMNS VARCHAR(50),
MONTH VARCHAR2(**10**) GENERATED ALWAYS AS
(SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
)
PARTITION BY LIST (MONTH)
(PARTITION p1 VALUES ('01','05','09'),
PARTITION p2 VALUES ('02','06','10'),
PARTITION p3 VALUES ('03','07','11'),
PARTITION p4 VALUES ('04','08','12'));
But I don't understand why column needs have length equal 10, and not 2, having in count the substring.
Edit: Execution trough sqlplus:
SQL> CREATE TABLE tabx(
2 DATE_VARCHAR VARCHAR2(10),
SOME_COLUMNS VARCHAR(50),
MONTH VARCHAR2(2) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
)
PARTITION BY LIST (MONTH)
(PARTITION p1 VALUES ('01','05','09'),
PARTITION p2 VALUES ('02','06','10'),
PARTITION p3 VALUES ('03','07','11'),
PARTITION p4 VALUES ('04','08','12'),
-- need default in case of bad data format
partition others values (default)
);
-- NOTE: this WON'T work now after adding VIRTUAL column
--insert into tabx values ('2015-12-01', 'ABC');
-- but this will (must specify columns)
3 4 5 6 7 8 9 10 11 12 13 insert into tabx(date_varchar,some_columns) values ('2016-01-01', 'XYZ');
MONTH VARCHAR2(2) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
*
ERROR at line 4:
ORA-12899: value too large for column "MONTH" (actual: 2, maximum: 8)
SQL> SQL> SQL> SQL> SQL> SQL> insert into tabx(date_varchar,some_columns) values ('2016-01-01', 'XYZ')
*
ERROR at line 1:
ORA-00942: table or view does not exist
Here is what worked for me. Its case 3 (virtual column). It techncally violates your client requirement that no new columns be created, although virtual, its still a column. Anyway:
CREATE TABLE tabx(
DATE_VARCHAR VARCHAR2(10),
SOME_COLUMNS VARCHAR(50),
MONTH VARCHAR2(2) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
)
PARTITION BY LIST (MONTH)
(PARTITION p1 VALUES ('01','05','09'),
PARTITION p2 VALUES ('02','06','10'),
PARTITION p3 VALUES ('03','07','11'),
PARTITION p4 VALUES ('04','08','12'),
-- need default in case of bad data format
partition others values (default)
);
-- NOTE: this WON'T work now after adding VIRTUAL column
--insert into tabx values ('2015-12-01', 'ABC');
-- but this will (must specify columns)
insert into tabx(date_varchar,some_columns) values ('2016-01-01', 'XYZ');
commit;
Note that the default partition is created as well.
ADDING SCRIPT OUTPUT HERE :
Running the above on 11.2 instance (with additional select from table) gives:
SQL> set lines 500
SQL> drop table tabx
Table dropped.
SQL> CREATE TABLE tabx(
DATE_VARCHAR VARCHAR2(10),
SOME_COLUMNS VARCHAR(50),
MONTH VARCHAR2(2) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
)
PARTITION BY LIST (MONTH)
(PARTITION p1 VALUES ('01','05','09'),
PARTITION p2 VALUES ('02','06','10'),
PARTITION p3 VALUES ('03','07','11'),
PARTITION p4 VALUES ('04','08','12'),
-- need default in case of bad data format
partition others values (default)
)
Table created.
SQL> -- NOTE: this WON'T work now after adding VIRTUAL column
SQL> --insert into tabx values ('2015-12-01', 'ABC');
SQL> -- but this will (must specify columns)
SQL> insert into tabx(date_varchar,some_columns) values ('2016-01-01', 'XYZ')
1 row created.
SQL> commit
Commit complete.
SQL> select * from tabx partition(p1)
DATE_VARCHAR SOME_COLUMNS MONTH
------------ -------------------------------------------------- -----
2016-01-01 XYZ 01
1 row selected.
EDIT :
Just a guess, but if the above doesn't work for you, perhaps the issue is with multi-byte encoding (which is why I was asking about your NLS_LANG settings on client and server). Anyway, what happens if you specify the MONTH column as:
MONTH VARCHAR2(2 CHAR) GENERATED ALWAYS AS (SUBSTR(DATE_VARCHAR,6,2)) VIRTUAL
Here I'm specifying 2 characters instead of 2 bytes. Again, just a guess, but easy to check.
Not sure if you have gone to 12c yet on your database. But, if you have then you can use a virtual invisible column to achieve what you are trying to do without affecting the database.
CREATE TABLE example
(
date_varchar VARCHAR2(10)
, some_columns VARCHAR(50)
, month NUMBER(2, 0) INVISIBLE GENERATED ALWAYS AS(EXTRACT(MONTH FROM TO_DATE(date_varchar, 'YYYY-MM-DD'))) VIRTUAL
)
PARTITION BY LIST(month)
(
PARTITION p1 VALUES (1, 5, 9)
, PARTITION p2 VALUES (2, 6, 10)
, PARTITION p3 VALUES (3, 7, 11)
, PARTITION p4 VALUES (4, 8, 12)
);
No rows affected (0.023 seconds)
Because the column is invisible it isn't required for an insert.
INSERT INTO example VALUES ('2015-12-01', 'ABC');
1 row affected (0.056 seconds)
And the row gets put into the right partition.
SELECT * FROM example PARTITION(p4);
+--------------+--------------+
| DATE_VARCHAR | SOME_COLUMNS |
+--------------+--------------+
| 2015-12-01 | ABC |
+--------------+--------------+
1 row selected (0.016 seconds)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.