DB2 error: SQL subselect error not recognized - sql

I think I just found an error in DB2 itself. When I run this code I expect it to throw an error when executing the delete statement (the subselect wrongly uses A_NAME instead of NAME). But: it acts as if there was no where clause and deletes all the rows in table NAMES!
CREATE TABLE NAMES (A_NAME VARCHAR(20));
CREATE TABLE OLDNAMES (NAME VARCHAR(20));
INSERT INTO NAMES VALUES ('ANNA'), ('ELLA'), ('JOHN'), ('EARL');
INSERT INTO OLDNAMES VALUES ('ELLA'), ('EARL');
-- this should throw an error message:
DELETE FROM NAMES WHERE A_NAME IN (SELECT A_NAME FROM OLDNAMES);
-- this should show ANNA & JOHN if the subselect
-- was correct, but shows nothing
SELECT * FROM NAMES;
-- cleanup
DROP TABLE NAMES;
DROP TABLE OLDNAMES;
I ran it on a DB2/LINUXX8664 10.5.9
Or is "not a bug, but a feature"?!

You are wrong. SQL has scoping rules for resolving column references in subqueries. If the column reference is not resolved in the inner query, then it looks to the outer query.
These are the rules of SQL, not specific to DB2.
That is SQL interprets your logic as:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT NAMES.A_NAME FROM OLDNAMES ON);
And this is valid -- if meaningless -- SQL.
This is why qualifying ALL column references is recommended. The better way to write this query is:
DELETE FROM NAMES
WHERE NAMES.A_NAME IN (SELECT ON.A_NAME FROM OLDNAMES ON);

Related

PostgreSQL update data error in excluded.column

i try update data from another table using PostgreSQL 9.6 following the document and stackoverflow advice with this query
1. this query is for finding the id_vertex of geom that close to lokasi_esb.geom. You can ignore this one, it works properly
CREATE TEMP TABLE temp1 AS
WITH kuery2 as(
SELECT id_esb, id_vertex, distant, rank() OVER (PARTITION BY id_esb ORDER BY distant asc) as ranked FROM table vertex)
select id_esb, id_vertex, distant, ranked
from kuery2
where ranked=1;
2. this query to update the lokasi_esb table with id_vertex_nearest column without excluded table. ////i already know it's wrong and i update on the number 3
INSERT INTO lokasi_esb(id_esb, id_vertex_nearest)
select id_esb,id_vertex
from temp1
ON CONFLICT (id_esb) DO UPDATE
SET lokasi_esb.id_vertex_nearest = temp1.id_vertex;
i got this error
ERROR: missing FROM-clause entry for table « temp1 »
SQL state: 42P01
Character: 634
3. this query to update the lokasi_esb table with id_vertex_nearest column with excluded table
INSERT INTO lokasi_esb(id_esb, id_vertex_nearest)
select id_esb,id_vertex
from temp1
ON CONFLICT (id_esb) DO UPDATE
SET lokasi_esb.id_vertex_nearest = excluded.id_vertex;
igot this error(transleted from indonesia)
ERROR: column excluded.id_vertex not yet exist
SQL state: 42703
Character: 634
So can anybody can help me figure out what happened here?
The column names from the "excluded" record refer to the columns of the target table. And the target column in the SET expression must not be prefixed with the table name (because you can't update a different table anyway)
So you need to use:
SET id_vertex_nearest = excluded.id_vertex_nearest

Sqlite copy data from temp table to another with conflict

i have db sqlite with main table and temp table. I want to import data from text file and then i want to insert data from temp table to main table.
INSERT INTO table(key) SELECT src.key FROM temp as src
ON CONFLICT (table.key) DO UPDATE SET to_insert = 0, to_delete =0;
When i am trying run this query then sqlite throw me this error.
Query 1 ERROR: near "DO": syntax error
Is possible insert data from another table with conflicts?
The select statement needs a where clause:
insert into mytable(key)
select key from temp where true
on conflict (key) do update set to_insert = 0, to_delete =0;
This pitfall is documented as parsing ambiguity (emphasis mine):
When the INSERT statement to which the UPSERT is attached takes its values from a SELECT statement, there is a potential parsing ambiguity. The parser might not be able to tell if the ON keyword is introducing the UPSERT or if it is the ON clause of a join. To work around this, the SELECT statement should always include a WHERE clause, even if that WHERE clause is just WHERE true.

New to SQL, getting "Error while executing SQL query on database 'flowers2019': no such column: SIGHTINGS.PERSON" When I try to test my trigger

I am trying to make a trigger that only lets me add a new PERSON if they are already included in the database. For example I can add a new entry for Donna, but not Joe because he's not in the database.
Table:
SIGHTINGS
NAME PERSON LOCATION SIGHTED
Alpine columbine Donna Chula Vista Campground 2006-07-03
Alpine columbine Jennifer Bright Star Mine 2006-07-11
CREATE TRIGGER validate_name
BEFORE INSERT ON SIGHTINGS
BEGIN
SELECT
CASE
WHEN NEW.PERSON NOT IN SIGHTINGS.PERSON THEN
RAISE (ABORT,'Error: Insert into the SIGHTINGS table references a person that is not found in the database.')
END;
END;
My tests:
INSERT INTO SIGHTINGS VALUES ("Douglas dustymaiden", "Joe", "Double Mountain", "2008-11-28")
and
INSERT INTO SIGHTINGS VALUES ("Douglas dustymaiden", "Donna", "Double Mountain", "2008-11-28")
For both tests I get Error while executing SQL query on database 'flowers2019':
no such column: SIGHTINGS.PERSON.
I apologize if this is an stupid question, I am brand new to SQL.
The clause :-
WHEN NEW.PERSON NOT IN SIGHTINGS.PERSON THEN
Is trying to access a table named PERSON in the attached database that has a schema name of SIGHTINGS, if that were to exist then it is effectively creating NOT IN (SELECT * FROM PERSON).
As per :-
The right-hand side of an IN or NOT IN operator can be a table name or table-valued function name in which case the right-hand side is understood to be subquery of the form "(SELECT * FROM name)".
SQL As Understood By SQLite - expression - The IN and NOT IN operators
What you probably want to use is :-
WHEN NEW.PERSON NOT IN (SELECT PERSON FROM SIGHTINGS)
The IN and NOT IN operators take an expression on the left and a list of values or a subquery on the right.
SQL As Understood By SQLite - expression - The IN and NOT IN operators
So you probably want :-
CREATE TRIGGER validate_name
BEFORE INSERT ON SIGHTINGS
BEGIN
SELECT
CASE
WHEN NEW.PERSON NOT IN (SELECT PERSON FROM SIGHTINGS)
RAISE (ABORT,'Error: Insert into the SIGHTINGS table references a person that is not found in the database.')
END;
END;

SQLite drop table when row in another table is deleted

I've been wrestling with setting up a trigger and keep getting the error:
SQL logic error near "DROP": syntax error
I have several tables main_table, other_one, other_two, etc.
main_table has several columns with the primary key column named filehash
The values in the primary key column of main_table are also the names of the other_* tables
So, if I delete a row in main_table with a primary key of other_one, I want the trigger to DROP the table other_one too
Here's the trigger statement that is producing the error
CREATE TRIGGER remove_other_one AFTER DELETE ON 'main_table'
WHEN (OLD.filehash == 'other_one')
BEGIN
DROP TABLE IF EXISTS 'other_one' ;
END remove_other_one;
EDIT: the 'fuller' error I get when I run the trigger statement in SQLite DB Browser is:
near "DROP": syntax error: CREATE TRIGGER remove_other_one AFTER DELETE ON 'main_table' WHEN (OLD.filehash == 'other_one') BEGIN DROP
Based on SQLite trigger doc I believe that it is not possible:
There is no option for DDL/dynamic SQL inside trigger.
I guess that you wanted to achieve something like PostgreSQL DBFiddle Demo 1 and Demo 2
You could handle your case in application code. Anyway table per date/customer/hash almost always indicates poor design and in long run will cause more problems.

Oracle view with multiple join is only recognize when use a quotes around - why?

I have encountered a strange behavior while executing an sql query on the Oracle view.
The view contains multiple joins. When I type a regular sql:
select * from vView - I receive the error that view is not found
select * from "vView" - The query is executed.
I am wondering why ?
Below is my sql:
CREATE OR REPLACE FORCE VIEW "TMSCODE"."vCountEventsData" ("EV_ID_NUMBER", "SI_ID", "EV_YEAR", "EV_INS_DATE", "EV_REM_DATE", "EV_AADT_TOT", "EV_AADT_DIR1", "EV_AADT_DIR2", "EV_REPORT", "DIRECTION", "CNAME", "STATION_DESC") AS
SELECT
"TMSCODE"."STC_EVENTS".EV_ID_NUMBER,
"TMSCODE"."STC_EVENTS".SI_ID,
"TMSCODE"."STC_EVENTS".EV_YEAR,
"TMSCODE"."STC_EVENTS".EV_INS_DATE,
"TMSCODE"."STC_EVENTS".EV_REM_DATE,
"TMSCODE"."STC_EVENTS".EV_AADT_TOT,
"TMSCODE"."STC_EVENTS".EV_AADT_DIR1,
"TMSCODE"."STC_EVENTS".EV_AADT_DIR2,
"TMSCODE"."STC_EVENTS".EV_REPORT,
"TMSCODE"."D_DIRECTION".DIRECTION,
"TMSCODE"."D_CONSULTANT".CNAME,
"TMSCODE"."D_STATION_TYPE".STATION_DESC
FROM
"TMSCODE"."STC_EVENTS"
INNER JOIN "TMSCODE"."D_DIRECTION" ON ("TMSCODE"."STC_EVENTS".EV_DIR = "TMSCODE"."D_DIRECTION".ID)
INNER JOIN "TMSCODE"."D_CONSULTANT" ON ("TMSCODE"."STC_EVENTS".EV_CONS = "TMSCODE"."D_CONSULTANT".ID)
INNER JOIN "TMSCODE"."D_STATION_TYPE" ON ("TMSCODE"."STC_EVENTS".EV_STATION_TYPE = "TMSCODE"."D_STATION_TYPE".ID)
WITH READ ONLY
The view was created with a mixed case name. If you issue the following (note no quotes around object names)
create view karl.vView
as
(select * from dba_tables);
The RDBMS will create the view and you will then find a line in dba_views (or user_views if you can't see dba_views) with the name VVIEW in upper case. Then select * from karl.vview or ... from KARL.VVIEW will work
If however you quote the objects names retains the case and you have to explicitly match it again with quotes. (This will also allow spaces in names and other bad scenarios. Worth knowing about to avoid and to be able to resolve when it does happen.
SYS#icedev> create table "TesT" (a int);
Table created.
SYS#icedev> insert into TesT values (1);
insert into TesT values (1)
*
ERROR at line 1:
ORA-00942: table or view does not exist
SYS#icedev> insert into test values (1);
insert into test values (1)
*
ERROR at line 1:
ORA-00942: table or view does not exist
SYS#icedev> insert into "TesT" values (1);
1 row created.
Of course to drop this table I had to use Drop table "TesT";
In Oracle, objects have an uppercase name unless quoted.
You used quotes to create an object with a mixed case name, so you must now ALWAYS refer to the object using a quoted identifier to say "Don't change this to uppercase".