I've a big SQL statement that looks similar to the one below.
As soon as there are more than 128 entries combined with union all, then I get this error: Too many Contexts of Relation-Procedure-Views. Maximum allowed is 255
How can I reformulate the query to get rid of the error?
There is no way to add this data to the database (it's in a script that does sanity checking of the database; the script has read-access only as the database can be in read-only mode).
Of the columns below:
id and identifier have distinct values in each row
id is the numeric ID and it have gaps that are known in advance
identifier is an alphanumeric name (so unlike the below query, you cannot generate identifier from id)
usage has two string values which are valid for certain groups of id (so I could put them in a separate union all construct)
comment has about 20 distinct string values which are valid for certain groups of id (so I could put them in a separate union all construct as well)
A query that reproduces this:
-- 20161024 - Too many Contexts of Relation-Procedure-Views. Maximum allowed is 255
with parameters as
(
select 1001 as id
, '1001' as usage
, 'PP_1001' as identifier
, '1001' as comment
from rdb$database
union all select 1002,'1002','PP_1002','1002' from rdb$database
union all select 1003,'1003','PP_1003','1003' from rdb$database
union all select 1004,'1004','PP_1004','1004' from rdb$database
union all select 1005,'1005','PP_1005','1005' from rdb$database
union all select 1006,'1006','PP_1006','1006' from rdb$database
union all select 1007,'1007','PP_1007','1007' from rdb$database
union all select 1008,'1008','PP_1008','1008' from rdb$database
union all select 1009,'1009','PP_1009','1009' from rdb$database
union all select 1010,'1010','PP_1010','1010' from rdb$database
union all select 1011,'1011','PP_1011','1011' from rdb$database
union all select 1012,'1012','PP_1012','1012' from rdb$database
union all select 1013,'1013','PP_1013','1013' from rdb$database
union all select 1014,'1014','PP_1014','1014' from rdb$database
union all select 1015,'1015','PP_1015','1015' from rdb$database
union all select 1016,'1016','PP_1016','1016' from rdb$database
union all select 1017,'1017','PP_1017','1017' from rdb$database
union all select 1018,'1018','PP_1018','1018' from rdb$database
union all select 1019,'1019','PP_1019','1019' from rdb$database
union all select 1020,'1020','PP_1020','1020' from rdb$database
union all select 1021,'1021','PP_1021','1021' from rdb$database
union all select 1022,'1022','PP_1022','1022' from rdb$database
union all select 1023,'1023','PP_1023','1023' from rdb$database
union all select 1024,'1024','PP_1024','1024' from rdb$database
union all select 1025,'1025','PP_1025','1025' from rdb$database
union all select 1026,'1026','PP_1026','1026' from rdb$database
union all select 1027,'1027','PP_1027','1027' from rdb$database
union all select 1028,'1028','PP_1028','1028' from rdb$database
union all select 1029,'1029','PP_1029','1029' from rdb$database
union all select 1030,'1030','PP_1030','1030' from rdb$database
union all select 1031,'1031','PP_1031','1031' from rdb$database
union all select 1032,'1032','PP_1032','1032' from rdb$database
union all select 1033,'1033','PP_1033','1033' from rdb$database
union all select 1034,'1034','PP_1034','1034' from rdb$database
union all select 1035,'1035','PP_1035','1035' from rdb$database
union all select 1036,'1036','PP_1036','1036' from rdb$database
union all select 1037,'1037','PP_1037','1037' from rdb$database
union all select 1038,'1038','PP_1038','1038' from rdb$database
union all select 1039,'1039','PP_1039','1039' from rdb$database
union all select 1040,'1040','PP_1040','1040' from rdb$database
union all select 1041,'1041','PP_1041','1041' from rdb$database
union all select 1042,'1042','PP_1042','1042' from rdb$database
union all select 1043,'1043','PP_1043','1043' from rdb$database
union all select 1044,'1044','PP_1044','1044' from rdb$database
union all select 1045,'1045','PP_1045','1045' from rdb$database
union all select 1046,'1046','PP_1046','1046' from rdb$database
union all select 1047,'1047','PP_1047','1047' from rdb$database
union all select 1048,'1048','PP_1048','1048' from rdb$database
union all select 1049,'1049','PP_1049','1049' from rdb$database
union all select 1050,'1050','PP_1050','1050' from rdb$database
union all select 1051,'1051','PP_1051','1051' from rdb$database
union all select 1052,'1052','PP_1052','1052' from rdb$database
union all select 1053,'1053','PP_1053','1053' from rdb$database
union all select 1054,'1054','PP_1054','1054' from rdb$database
union all select 1055,'1055','PP_1055','1055' from rdb$database
union all select 1056,'1056','PP_1056','1056' from rdb$database
union all select 1057,'1057','PP_1057','1057' from rdb$database
union all select 1058,'1058','PP_1058','1058' from rdb$database
union all select 1059,'1059','PP_1059','1059' from rdb$database
union all select 1060,'1060','PP_1060','1060' from rdb$database
union all select 1061,'1061','PP_1061','1061' from rdb$database
union all select 1062,'1062','PP_1062','1062' from rdb$database
union all select 1063,'1063','PP_1063','1063' from rdb$database
union all select 1064,'1064','PP_1064','1064' from rdb$database
union all select 1065,'1065','PP_1065','1065' from rdb$database
union all select 1066,'1066','PP_1066','1066' from rdb$database
union all select 1067,'1067','PP_1067','1067' from rdb$database
union all select 1068,'1068','PP_1068','1068' from rdb$database
union all select 1069,'1069','PP_1069','1069' from rdb$database
union all select 1070,'1070','PP_1070','1070' from rdb$database
union all select 1071,'1071','PP_1071','1071' from rdb$database
union all select 1072,'1072','PP_1072','1072' from rdb$database
union all select 1073,'1073','PP_1073','1073' from rdb$database
union all select 1074,'1074','PP_1074','1074' from rdb$database
union all select 1075,'1075','PP_1075','1075' from rdb$database
union all select 1076,'1076','PP_1076','1076' from rdb$database
union all select 1077,'1077','PP_1077','1077' from rdb$database
union all select 1078,'1078','PP_1078','1078' from rdb$database
union all select 1079,'1079','PP_1079','1079' from rdb$database
union all select 1080,'1080','PP_1080','1080' from rdb$database
union all select 1081,'1081','PP_1081','1081' from rdb$database
union all select 1082,'1082','PP_1082','1082' from rdb$database
union all select 1083,'1083','PP_1083','1083' from rdb$database
union all select 1084,'1084','PP_1084','1084' from rdb$database
union all select 1085,'1085','PP_1085','1085' from rdb$database
union all select 1086,'1086','PP_1086','1086' from rdb$database
union all select 1087,'1087','PP_1087','1087' from rdb$database
union all select 1088,'1088','PP_1088','1088' from rdb$database
union all select 1089,'1089','PP_1089','1089' from rdb$database
union all select 1090,'1090','PP_1090','1090' from rdb$database
union all select 1091,'1091','PP_1091','1091' from rdb$database
union all select 1092,'1092','PP_1092','1092' from rdb$database
union all select 1093,'1093','PP_1093','1093' from rdb$database
union all select 1094,'1094','PP_1094','1094' from rdb$database
union all select 1095,'1095','PP_1095','1095' from rdb$database
union all select 1096,'1096','PP_1096','1096' from rdb$database
union all select 1097,'1097','PP_1097','1097' from rdb$database
union all select 1098,'1098','PP_1098','1098' from rdb$database
union all select 1099,'1099','PP_1099','1099' from rdb$database
union all select 1100,'1100','PP_1100','1100' from rdb$database
union all select 1101,'1101','PP_1101','1101' from rdb$database
union all select 1102,'1102','PP_1102','1102' from rdb$database
union all select 1103,'1103','PP_1103','1103' from rdb$database
union all select 1104,'1104','PP_1104','1104' from rdb$database
union all select 1105,'1105','PP_1105','1105' from rdb$database
union all select 1106,'1106','PP_1106','1106' from rdb$database
union all select 1107,'1107','PP_1107','1107' from rdb$database
union all select 1108,'1108','PP_1108','1108' from rdb$database
union all select 1109,'1109','PP_1109','1109' from rdb$database
union all select 1110,'1110','PP_1110','1110' from rdb$database
union all select 1111,'1111','PP_1111','1111' from rdb$database
union all select 1112,'1112','PP_1112','1112' from rdb$database
union all select 1113,'1113','PP_1113','1113' from rdb$database
union all select 1114,'1114','PP_1114','1114' from rdb$database
union all select 1115,'1115','PP_1115','1115' from rdb$database
union all select 1116,'1116','PP_1116','1116' from rdb$database
union all select 1117,'1117','PP_1117','1117' from rdb$database
union all select 1118,'1118','PP_1118','1118' from rdb$database
union all select 1119,'1119','PP_1119','1119' from rdb$database
union all select 1120,'1120','PP_1120','1120' from rdb$database
union all select 1121,'1121','PP_1121','1121' from rdb$database
union all select 1122,'1122','PP_1122','1122' from rdb$database
union all select 1123,'1123','PP_1123','1123' from rdb$database
union all select 1124,'1124','PP_1124','1124' from rdb$database
union all select 1125,'1125','PP_1125','1125' from rdb$database
union all select 1126,'1126','PP_1126','1126' from rdb$database
union all select 1127,'1127','PP_1127','1127' from rdb$database
union all select 1128,'1128','PP_1128','1128' from rdb$database
--union all select 1129,'1129','PP_1129','1129' from rdb$database
)
select parameters.id
, parameters.usage
, parameters.identifier
, parameters.comment
from parameters
where parameters.id <> -1
order by parameters.id
A construct like the one below should get me going.
The params is a table in the database that needs to be compared to the artificial parameters table that is sparsely filled.
Techniques used:
recursive query to generate a sequence of ID values in IDs
case constructs to fill the columns
In the actual query there will be a case with when and then for all validId values and smaller case constructs for the columns needing less values.
Query without error:
select parameters.id
, parameters.usage
, parameters.identifier
, parameters.comment
, params.ID param_id
, params.AVALUE
, params.DESCRIPTION
from
(
with recursive IDs as
(
select 0 as ID from rdb$database
union all
select 1 + ID from IDs where ID < 1000
)
select
ID
, case
when ((ID = 999) or (ID between 0 and 130))
then 1
else 0
end as validId
, case
when ID in
(
3,
12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
41, 42, 46, 47,
50, 51, 52, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 79,
80, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 129,
999
)
then 'used'
else 'unused'
end as usage
, '' as identifier
, '' as comment
from
IDs
) parameters
full outer join params
on params.ID = parameters.id
where parameters.validId = 1
order by params.id, parameters.id
I have the following SQL:
SELECT SUM(theNumberCol) qty, TRUNC(theDateCol, 'WW') weekDate
FROM theTable
GROUP BY TRUNC(theDateCol, 'WW');
This works fine for finding the sum of theNumberCol for each week. The problem is that the week seems to start on a Tuesday. For example "12/17/2013 8:56:05 AM" is truncated to "12/17/2013" while "12/16/2013 5:09:25 AM" is truncated to "12/10/2013".
How does Oracle determine which day to start the week?
Can I change the week to start on Saturday?
There are two different calculations available: classic oracle, which calculates week=int(dayOfYear+6)/7, and iso mode, which uses ISO 8601. Format WW uses the classic calculation, while format IW uses the ISO standard.
So as you see, WW does not start the week on any fixed day of the week, it just starts the week on january 1st, whichever day that is. IW is what should work for you if you live in any country that follows international standards.
Take 7 days away from the truncated date and then find the next Saturday from that date:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE theTable ( theNumberCol, theDateCol ) AS
SELECT 1, TO_DATE( '20131202 23:15:52', 'YYYYMMDD HH24:MI:SS' ) FROM DUAL
UNION ALL SELECT 2, TO_DATE( '20131203', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 3, TO_DATE( '20131204', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 4, TO_DATE( '20131205', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 5, TO_DATE( '20131206', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 6, TO_DATE( '20131207', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 7, TO_DATE( '20131208', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 8, TO_DATE( '20131209', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 9, TO_DATE( '20131210', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 10, TO_DATE( '20131211', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 11, TO_DATE( '20131212', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 12, TO_DATE( '20131213', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 13, TO_DATE( '20131214', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 14, TO_DATE( '20131215', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 15, TO_DATE( '20131216', 'YYYYMMDD' ) FROM DUAL
UNION ALL SELECT 16, TO_DATE( '20131217', 'YYYYMMDD' ) FROM DUAL;
Query 1:
SELECT SUM(theNumberCol) AS qty,
NEXT_DAY( TRUNC( theDateCol ) - INTERVAL '7' DAY, 'SATURDAY' ) weekDate
FROM theTable
GROUP BY
NEXT_DAY( TRUNC( theDateCol ) - INTERVAL '7' DAY, 'SATURDAY' )
ORDER BY
weekDate ASC
Results:
| QTY | WEEKDATE |
|-----|---------------------------------|
| 15 | November, 30 2013 00:00:00+0000 |
| 63 | December, 07 2013 00:00:00+0000 |
| 58 | December, 14 2013 00:00:00+0000 |
It depends on your local NLS_TERRITORY which is the first day. E.g. 'germany' will return monday. 'america' returns sunday, 'egypt' returns saturday.
Use alter session set nls_territory ='germany'; for example
I don't know that changing the behavior of TRUNC(...) is possible (and having it deviate from the documentation is likely to cause problems). However, there is another solution (one that might perform better):
You want what's known as a Calendar Table (example is SQL Server, but the basic concept applies). If you don't have one, I recommend creating (and indexing) one. For example, regardless of if your week starts on a Saturday, using the calendar table then makes this trivial:
SELECT
FROM WeekRange.weekStart, SUM(theTable.theNumberCol)
JOIN (SELECT dateValue as weekStart, dateValue + 7 as nextWeekStart
FROM Calendar
WHERE nameOfDay = 'Saturday') WeekRange
ON theTable.theDateCol >= WeekRange.weekStart
AND theTable.theDateCol < WeekRange.nextWeekStart
GROUP BY WeekRange.weekStart
Add/replace conditions as necessary, of course. This version is also more likely to use any indices over the relevant columns.