I'm stuck with creating a view in Oracle, but before I create the view, I always test it first and I always got this error: Ora-00904.
This is the situation. I have this one Set of Query let say Query A that I need to combined using UNION ALL with the Query A itself with only few modifications applied to create another bigger Set of Query - Query B. The main constraint that keeps me on doing this is the Database Design, and I'm not in the position in the company to change it, so I have to adapt to it. Query A unions Query A for 6 times creating Query B. The additional Major constraint is Query B is from 1 database user only, but there are 54 database users with the same structures that I need to fetch the same query. Query B (db user1) unions Query B (db user2) unions Query B (db user3) and so on until 54 then finally creating Query C --- the final output. My scrip has already reached 6048 lines, then I got this problem that I don't get when I test Query A and Query B. All my table names, owner names, and column names are all correct but I got that error.
This is the code (that needs to be repeated for 54x6 times) - the Query A. Query B applies some similar modification only.:
Select
'2013' "YEAR",
Upper(a.text_month) "MONTH",
Upper('Budget') "VERSION",
case
when length(b.level1_name) > 5 then 'Parent'
else 'SUBSIDIARIES'
end "COMPANY_GROUP",
case
when length(b.level1_name) < 6 and b.level1_name <> '1000' then 'Subsidiaries'
else '1000 Parent'
end "COMPANY",
case
when length(b.level1_name) < 6 and b.level1_name <> '1000' then 'SUBS'
else '1000'
end "COMPANY_CODE",
case
when length(b.level1_name) > 5 then 'Parent'
else 'SUBSIDIARIES'
end "COMPANY_NAME",
b.level1_displayname "DIVISION",
b.level1_name "DIVISION_CODE",
case
when length(b.level1_name) > 5 then ltrim(upper(substr(b.level1_displayname, 8)))
else upper(ltrim(substr(b.level1_displayname, 10)))
end "DIVISION_NAME",
upper(a.text_nature_of_trip) "NATURE_OF_TRAVEL",
upper(a.text_placeeventstraining) "TRAVEL_DETAILS",
upper(a.text_country) "COUNTRY",
a.text_name_of_employee "EMPLOYEE_NAME", a.float_no_of_attendees "NO_OF_ATTENDEES",
a.text_sponsored "SPONSORED",
a.text_remarks "REMARKS",
'OTHER TRAVEL EXPENSES' "COST_ELEMENT",
a.FLOAT_702120005_OTHER_TRAVEL_E "AMOUNT"
From PUBLISH_PNL_AAAA_2013.et_travel_transaction a,
PUBLISH_PNL_AAAA_2013.cy_2elist b
Where a.elist = b.level3_iid
ORA-00904 is "invalid column name" -- either you've spelled the column name wrongly, or prefixed it with the wrong table alias, omitted quotes from a string literal, or any number of other issues.
Check the point in the code that the error message mentions for mistakes like that.
Related
I am accessing an 11.7 OE Enterprise RDBMS. I have two simple queries, one which works another which doesn't. In the queries below the LAB_VALUE field is a varchar data type. The first query returns 106 rows with no issues. The second query dies immediately.
Query 1;
SELECT to_number(LAB_VALUE) LAB_VALUE
FROM labrec_view
WHERE lab_yr_mon = 202006 AND
FACILITY_CODE = 'BUF' AND
LAB_RESULT_CODE = 'ALBUMIN'
Query2;
SELECT to_number(LAB_VALUE) LAB_VALUE
FROM labrec_view
WHERE lab_yr_mon = 202006 AND
FACILITY_CODE = 'BUF' AND
LAB_RESULT_CODE = 'ALBUMIN' and
to_number(LAB_VALUE) > 4
The error received is;
SQLState=HY000
ErrorCode=-20232
[DataDirect][OpenEdge JDBC Driver][OpenEdge] Invalid number string (7498)
I am at a loss. There is an KB atricle;
https://knowledgebase.progress.com/articles/Article/Invalid-number-string-7498-returned-by-SQL-query-on-OE-10-2B
But it seems to refer to older versions of OpenEdge and specifically states 11.7 should correct the issue.
I am not a Progress DB person, and I only have access to query views in the DB as a specific R/O user.
Where do I go from here in troubleshooting?
Edit:
Someone suggested the to_number (in the where clause) might be causing a problem because some data which I don't see may not be numeric. So I used the following query with the same error results;
SELECT LAB_VALUE_TEST
from
(
SELECT to_number(LAB_VALUE) LAB_VALUE_TEST
FROM labrec_view
WHERE lab_yr_mon = 202106 AND
FACILITY_CODE = 'BUF' AND
LAB_RESULT_CODE = 'ALBUMIN'
) iq
WHERE iq.LAB_VALUE_TEST >4;
at a guess, because you're using an expression ( "to_number(LAB_VALUE) > 4" ) the LAB_VALUE field has to be checked to see if it is greater than 4
if there "where" phrase does not short-circuit then all labrec records have to be checked , and there may be some with an invalid value for a number
I need to merge some randomly uppercased data that has been collected in an SQLite table key_val, such that key is always lowercase and no vals are lost. There is a unique compound index on key,val.
The initial data looks like this:
key|val
abc|1
abc|5
aBc|1
aBc|5
aBc|3
aBc|2
AbC|1
abC|3
The result after the merge would be
key|val
abc|1
abc|2
abc|3
abc|5
In my programmer brain, I would
for each `key` with upper case letters;
if a lower cased `key` is found with the same value
then delete `key`
else update `key` to lower case
Re implementing the loop has a sub query for each row found with upper case letters, to check if the val already exists as a lower case key
If it does, I can delete the cased key.
From there I can UPDATE key = lower(key) as the "duplicates" have been removed.
The first cut of the programming method of finding the dupes is:
SELECT * FROM key_val as parent
WHERE parent.key != lower(parent.key)
AND 0 < (
SELECT count(s.val) FROM key_val as s
WHERE s.key = lower(parent.key) AND s.val = parent.val
)
ORDER BY parent.key DESC;
I'm assuming there's a better way to do this in SQLite? The ON CONFLICT functionality seems to me like it should be able to handle the dupe deletion on UPDATE but I'm not seeing it.
First delete all the duplicates:
DELETE FROM key_val AS k1
WHERE EXISTS (
SELECT 1
FROM key_val AS k2
WHERE LOWER(k2.key) = LOWER(k1.key) AND k2.val = k1.val AND k2.rowid < k1.rowid
);
by keeping only 1 combination of key and val with the min rowid.
It is not important if you kept the key with all lower chars or not, because the 2nd step is to update the table:
UPDATE key_val
SET key = LOWER(key);
See the demo.
Honestly it might just be easier to create a new table and then insert into it. As it seems you really just want a distinct select here, use:
INSERT INTO kev_val_new ("key", val)
SELECT DISTINCT LOWER("key"), val
FROM key_val;
Once you have populated the new table, you may drop the old one, and then rename the new one to the previous name:
DROP TABLE key_val;
ALTER TABLE key_val_new RENAME TO key_val;
I agree with #Tim that it would be easire to re-create table using simple select distict lower().. statement, but that's not always easy if table has dependant objects (indexes, triggers, views). In this case this can be done as sequence of two steps:
insert lowered keys which are not still there:
insert into t
select distinct lower(tr.key) as key, tr.val
from t as tr
left join t as ts on ts.key = lower(tr.key) and ts.val = tr.val
where ts.key is null;
now when we have all lowered keys - remove other keys:
delete from t where key <> lower(key);
See fiddle: http://sqlfiddle.com/#!5/84db50/11
However this method assumes that key is always populated (otherwise it would be a strange key)
If vals can be null then "ts.val = tr.val" should be replaced with more complex stuff like ifnull(ts.val, -1) = ifnull(tr.val, -1) where -1 is some unused value (can be different). If we can't assume any unused value like -1 then it should be more complex check for null / not null cases.
I have an ASP.NET Web API app using Oracle's Entity Framework driver. I have an entity defined for a view as follows:
CREATE OR REPLACE FORCE VIEW "PHASE_TWO"."EDIPRODUCT" ("ID", "STK_NUM", "TITLE", "ISBN", "UPC", "ITEMNO", "LONGFORMAT", "ABRIDGED", "WEB_TITLES_ID", "OCLC", "GENRE", "RELYEAR", "ORIG_REL", "LANG", "ORIG_STKNUM", "PUBLISHER", "PEOPLELIST", "SALES_ORG", "NOT_AVAIL") AS
SELECT sap_product.id,
sap_product.stk_num,
sap_product.longdesc AS title,
sap_product.isbn,
sap_product.upc,
sap_product.itemno,
sap_product.longformat,
sap_product.abridged,
mwt_product.web_titles_id,
mwt_product.oclc,
mwt_product.genre,
mwt_product.RELYEAR,
sap_product.orig_rel,
sap_product.lang,
sap_product.orig_stknum,
UPPER (publisher.name) publisher,
(SELECT LISTAGG (p.FULLNAME, ', ') WITHIN GROUP (
ORDER BY pp.rank) AS People
FROM people p
JOIN product_people pp
ON p.id = pp.peopleid
WHERE pp.stk_num = sap_product.stk_num
GROUP BY pp.STK_NUM
) PeopleList,
sppg.PRICING_TYPE as sales_org,
sap_product.not_avail
FROM sap_product
JOIN mwt_product ON sap_product.stk_num = mwt_product.stk_num
JOIN publisher ON mwt_product.publisherid = publisher.id
JOIN SAP_PRODUCT_PRICING_GROUP sppg on sppg.STK_NUM = mwt_product.stk_num and sppg.MARKED_FOR_DELETION = 0
WHERE mwt_product.WEB_PRODUCTS_ID > 0;
This view works as expected in SQL Developer. My getEDIPRODUCT function (yes, it's VB.NET) in my controller is as follows:
' GET: odata/EDIPRODUCTs
<EnableQuery>
Function GetEDIPRODUCT() As IQueryable(Of EDIPRODUCT)
Dim results As IQueryable
results = db.EDIPRODUCT
For Each _product In results
Console.Write(_product)
Next
Return results
End Function
I just added the for loop in order to inspect the results. What I see when I inspect the results is the same product record is returned for each row. The value for the ID is duplicate and the only other field that should have variant values (sppg.PRICING_TYPE as sales_org) also just repeats.
I have other views where this does not occur. The correct number of records are always returned, but the first record retrieved is always just repeated in each row of the result set. Any idea what could be going on here?
I never actually resolved this issue and am still interested in why this fails, but I rewrote the portion of the app that uses this view to use OData's $expand to retrieve the related data.
My code follows:
SELECT COUNT(_id) AS count FROM general WHERE _id = 1 CASE WHEN count > 0 THEN UPDATE general SET userGivenId = 'xxx' WHERE _id = 1 ELSE INSERT INTO general (userGivenId) VALUES ('xxx' ) END
With the error:
android.database.sqlite.SQLiteException: near "CASE": syntax error: , while compiling: SELECT COUNT(_id) AS count FROM general WHERE _id = 1 CASE WHEN count > 0 THEN UPDATE general SET userGivenId = 'xxx' WHERE _id = 1 ELSE INSERT INTO general (userGivenId) VALUES ('xxx' ) END
This is the shortest query I will use. Why I do this is because my other queries will have rows that needs to be updated but some may not be touched. Using replace will replace all the data (at least that is how it works for me on my Android phone). For instance my File class will have a filePath, but sometimes the response from the server will return null and I am only to update the File IF the server returns a new File.
Did I forget to write anything?
SQLite does not have any control logic because this would not make sense in an embedded database (there is no separate server machine/process whose asynchronous execution could improve performance).
CASE can be used only for expressions, not for entire commands.
Handle the control logic in your app:
Cursor c = db.rawQuery("SELECT 1 FROM general WHERE _id = 1", null);
if (c.moveToFirst())
db.execSQL("UPDATE general SET userGivenId = 'xxx' WHERE _id = 1");
else
db.execSQL("INSERT INTO general (userGivenId) VALUES ('xxx')");
For these particular commands, if you have a unique constraint on the _id column (and a primary key is constrained to be unique), you can use the INSERT OR REPLACE command:
INSERT OR REPLACE INTO general(_id, userGivenId) VALUES(1, 'xxx')
I have a problem while inserting based on select query
I have a schema in the database with a parent-child relationship that looks like the following
A
B
C
G
L
F
C
G
L
Notice how Element c is reused, because it´s aviable twice with different parent id, but element g is only aviable once, since the id of c is the same in both cases. The select prints everything as expected with the following query
select id,
parent_id,
label
from table
start with parent_id is null
connect by nocycle prior id = parent_id
order siblings by sort
i am having around 2500 elements in this table, but in the end around 4000 are displayed because a few elemnts should be displayed multiple times at different places.
So, to identify both, the first and second g as unique elements, i have written the following insert statement
insert into other_tale (id, parent_id, label)
select create_id new_id,
prior ???,
label,
from table
start with parent_id is null
connect by nocycle prior id = parent_id
order siblings by sort;
Here i am calling a procedure to generate a new id for each raw that has been found. Now i am stuck at the part where i do recieve the new id of the parent element. I know that i can refer to the prior parent_raw in the table beeing select, but am i able to somehow refer to the column new_id of the parent_element in the select?
Create a package with 1 associative array id_cache and 2 functions: f_clear_cache and f_generate_id.
f_clear_cache deletes the cached ids - id_cache.delete.
f_generate_id takes id as argument and returns the new_id
check if the new_id was already generated - id_cache.exists(id)
if not, generate the new_id and cache it - id_cache(id) := new_id
return new_id - return id_cache(id)
finally use the function in your sql statement
insert into other_tale (id, parent_id, label)
select my_package.f_generate_id(id),
my_package.f_generate_id(parent_id),
label
...
note: do not forget to call f_clear_cache when you want to generate new set of ids within the same session.