Oracle error : ORA-00905: Missing keyword - sql

Excuting the line of SQL:
SELECT *
INTO assignment_20081120
FROM assignment ;
against a database in oracle to back up a table called assignment gives me the following ORACLE error:
ORA-00905: Missing keyword

Unless there is a single row in the ASSIGNMENT table and ASSIGNMENT_20081120 is a local PL/SQL variable of type ASSIGNMENT%ROWTYPE, this is not what you want.
Assuming you are trying to create a new table and copy the existing data to that new table
CREATE TABLE assignment_20081120
AS
SELECT *
FROM assignment

First, I thought:
"...In Microsoft SQL Server the
SELECT...INTO automatically creates
the new table whereas Oracle seems to
require you to manually create it
before executing the SELECT...INTO
statement..."
But after manually generating a table, it still did not work, still showing the "missing keyword" error.
So I gave up this time and solved it by first manually creating the table, then using the "classic" SELECT statement:
INSERT INTO assignment_20081120 SELECT * FROM assignment;
Which worked as expected. If anyone come up with an explanaition on how to use the SELECT...INTO in a correct way, I would be happy!

You can use select into inside of a PLSQL block such as below.
Declare
l_variable assignment%rowtype
begin
select *
into l_variable
from assignment;
exception
when no_data_found then
dbms_output.put_line('No record avialable')
when too_many_rows then
dbms_output.put_line('Too many rows')
end;
This code will only work when there is exactly 1 row in assignment. Usually you will use this kind of code to select a specific row identified by a key number.
Declare
l_variable assignment%rowtype
begin
select *
into l_variable
from assignment
where ID=<my id number>;
exception
when no_data_found then
dbms_output.put_line('No record avialable')
when too_many_rows then
dbms_output.put_line('Too many rows')
end;

Though this is not directly related to the OP's exact question but I just found out that using a Oracle reserved word in your query (in my case the alias IN) can cause the same error.
Example:
SELECT * FROM TBL_INDEPENTS IN
JOIN TBL_VOTERS VO on IN.VOTERID = VO.VOTERID
Or if its in the query itself as a field name
SELECT ..., ...., IN, ..., .... FROM SOMETABLE
That would also throw that error. I hope this helps someone.

If you backup a table in Oracle Database. You try the statement below.
CREATE TABLE name_table_bk
AS
SELECT *
FROM name_table;
I am using Oracle Database 12c.

Late answer, but I just came on this list today!
CREATE TABLE assignment_20101120 AS SELECT * FROM assignment;
Does the same.

Related

SQL command not ended properly at pkg_test

I have to write a stored procedure that starts copying the data from a table 'company' into a staging table 'company_stg' if no records for that date are present in it.
I have the following code :
CREATE OR REPLACE
PACKAGE BODY PKG_TEST AS
PROCEDURE SP_BILLING AS
BEGIN
EXECUTE IMMEDIATE 'SELECT * FROM COMPANY INTO COMPANY_STG
WHERE NOT EXISTS (SELECT * FROM COMPANY_STG WHERE AS_OF_DATE = "2023-02-08")';
END;
END PKG_TEST;
I AM GETTING THE ERROR "SQL COMMAND NOT PROPERLY ENDED"
company * company_stg have as_of_date as a column. rest all are same.
please help me with this
I have also tried
if not exists (SELECT * FROM COMPANY_STG WHERE AS_OF_DATE = "2023-02-08")
then
select from company into company_stg
So many things look bad in that piece of code...
First, why use dynamic SQL execute immediate? It's best to avoid dynamic SQL as much as possible because it leads to runtime errors and requires pretty much instrumentation so that it may be debugged. Generally you use dynamic SQL when you do not know beforehand the name of a table it will operate on, which is not the case for you. You definitely know you have to work with tables COMPANY and COMPANY_STG. Is it not so?
Then, it doesn't look like you have read the manual to see an insert select.
When you insert into a table, it's best to give the list of columns into which you actually insert data. If one alters that table and adds one or more than one column, the insert which does not have the list of columns will crash.
Thus, to insert into COMPANY_STG data from COMPANY, the SQL should look like below:
insert into company_stg(
... ---- here should be the list of columns you insert data into
)
select
... --- here should the source columns you are willing to insert
from company c
where not exists (
select 1
from company_stg cs
where cs.as_of_date= --- what is the condition??? I did not understand
)
;
You have not given the structures for those tables, so that I can't give you the columns to select and to insert into. Nor did I really understand what the condition for inserting data should be.
SELECT does not perform a copy and SELECT * FROM COMPANY INTO COMPANY_STG is not valid syntax. You want to use an INSERT statement to do that (and check if there is any row first):
CREATE OR REPLACE PACKAGE BODY PKG_TEST AS
PROCEDURE SP_BILLING
AS
BEGIN
DECLARE
v_staged_count NUMBER;
BEGIN
SELECT 1
INTO v_staged_count
FROM COMPANY_STG
WHERE AS_OF_DATE = DATE '2023-02-08'
FETCH FIRST ROW ONLY; -- We don't care how many rows so stop after finding
-- the first one.
-- Stop as rows have been found.
RETURN;
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Continue
NULL;
END;
INSERT INTO company_stg
SELECT *
FROM COMPANY;
END;
END PKG_TEST;
/
fiddle

How to compare two values in different tables with a TRIGGER SQL?

CREATE TRIGGER Comparer_Prix
BEFORE UPDATE ON ARTICLE
FOR EACH ROW BEGIN
SELECT ARTICLE.PRIXVENTE, ARTICLE.N_PRODUIT, ARTICLE.N_FABRICANT, LIEN_FABRICANT_PRODUIT.PRIXFABRICANT, LIEN_FABRICANT_PRODUIT.N_PRODUIT, LIEN_FABRICANT_PRODUIT.N_FABRICANT
FROM ARTICLE, LIEN_FABRICANT_PRODUIT
WHERE ARTICLE.N_FABRICANT=LIEN_FABRICANT_PRODUIT.N_FABRICANT AND ARTICLE.N_PRODUIT=LIEN_FABRICANT_PRODUIT.N_PRODUIT;
IF (NEW.PRIXVENTE< PRIXFABRICANT) THEN RAISE_APPLICATION_ERROR(-20001, 'Refusé');
END IF;
END;
I am trying to create a trigger that codes the following rule: the sales price must always be higher than the manufacturing price.
Here the errors I get:
Error(2,3): PL/SQL: SQL Statement ignored
Error(2,69): PL/SQL: ORA-00904: "LIEN_FABRICANT_PRODUIT"."PRIXFABRICANT" : invalid identifier
Error(2.92): PLS-00302: The component "PRIXFABRICANT" must be declared.
Error(5,3): PL/SQL: Statement ignored
Error(5,10): PLS-00201: the identifier 'NEW.PRIXVENTE' must be declared.
It is not new, but :new (you're missing a colon).
Though, that's not the only issue here; you can't select from a table which is just being modified; mutating table error is expected. Lucky you, you don't have to select from article as you can reference its values using the same :new value.
ORA-00904 means that you've used a column name which doesn't exist in that table. As you didn't post tables' descriptions, I'm simply repeating what you wrote. Fix it yourself.
Something like this:
create or replace trigger comparer_prix
before update on article
for each row
declare
l_prixfabricant lien_fabricant_produit.prixfabricant%type;
begin
select prixfabricant
into l_prixfabricant
from lien_fabricant_produit
where n_fabricatn = :new.n_fabricant
and n_produit = :new.n_produit;
if :new.prixvente < l_prixfabricant then
raise_application_error(-20001, 'Refusé');
end if;
end;
/
Also, it wouldn't harm if you learnt how to properly format code and make it easier to read. Use table aliases (instead of those lengthy table names).
If You compare two tables use:
... WHERE ... AND EXISTS(SELECT * FROM <TAB_COMPARE>)

Oracle PL/SQL - BEFORE INSERT 'table does not exist' error?

I'm taking my first steps in Pl/SQL and am struggling with triggers. I've tried creating the trigger below but am receiving this error:
Error at line 2: PL/SQL: SQL Statement ignored
PL/SQL: ORA-00942: table or view does not exist
To clarify: I have checked the name of the table over and over, and it does exist. It is also in the same schema as the trigger I'm trying to create. The 'customer_seq.NEXTVAL' refers to a sequence created previously that runs without errors.
The code is as follows:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
INSERT INTO customer_id VALUES ('c-', customer_seq.NEXTVAL);
END;
Thanks in advance for any help.
You probably intend something like this:
CREATE TRIGGER new_customer
BEFORE INSERT ON customer
FOR EACH ROW
BEGIN
SELECT customer_seq.NEXTVAL INTO :NEW.customer_id
FROM dual;
END;
It is unclear what the purpose of 'C_' is. If it is part of the customer id, I would advise you to stick to numbers.
Also note that more recent versions of Oracle support generated always as identity -- which is much preferred over defining a sequence and trigger.

SELECT after WITH returns no rows if in an explicit transaction

WITH generated_id AS (
INSERT INTO ... RETURNING id
)
SELECT id FROM generated_id;
returns 42, whereas
BEGIN;
WITH generated_id AS (
INSERT INTO ... RETURNING id
)
SELECT id FROM generated_id;
COMMIT;
returns nothing. Why?
Update:
I just found that WITH is irrelevant, because even a single select doesn't work:
SELECT something FROM some_table;
returns rows.
BEGIN;
SELECT something FROM some_table;
COMMIT;
returns no rows.
Update 2:
I thought BEGIN and START TRANSACTION are the exact same things. Anyways, I tried all possible combinations but none of them works for me.
I'm using this free postgres service but now I tested it with SQL Fiddle and it is not complaining.
It is strange however that if I don't put a ; at the end of the SELECT line, my DB engine gives me a syntax error and if I put it there using SQL Fiddle, it tells me that Explicit commits are not allowed.
So it's still very unclear for me what is exactly happening. Whether it only works in SQL Fiddle because it really isn't running my query in an explicit transaction and if it would then the results would be the same: no rows, just as how my DB engine behaves.
I'm unfortunately not able to test it on other servers, but if someone has a reliable postgres config, maybe they could try it for me whether it runs and tell me.
This will return nothing in most clients because you only see what the last command returned:
BEGIN;
SELECT something FROM some_table;
COMMIT;
Try instead:
BEGIN;
SELECT something FROM some_table;
But don't forget to COMMIT or ROLLBACK later to terminate the open transaction.
SQL Fiddle does not allow explicit transaction wrappers. I quote:
All SQL queries are run within a transaction that gets immediately rolled-back after the SQL executes.
BEGIN; issued inside an open transaction only issues a WARNING - which is not displayed in SQL Fiddle (you see a result with 0 rows).
COMMIT; raises the error you saw.
And in your attempt with omitting the semicolon after the SELECT, COMMIT is interpreted as table alias:
BEGIN;
SELECT something FROM some_table
COMMIT;
... is equivalent to:
BEGIN;
SELECT something FROM some_table AS commit;
So that's another misunderstanding.
Did you try saying BEGIN WORK?
I think you need to start with that, then you can end it with COMMIT
Try to start with:
BEGIN TRANSACTION;
Then end with:
END TRANSACTION;

Problem with trigger in oracle

I'm new in oracle and i don't know what is wrong with this trigger:
CREATE OR REPLACE TRIGGER "propuesta_casas"
BEFORE INSERT ON "PROPUESTA_TIENDA_BARRIO"
FOR EACH ROW
WHEN (new."CASASCAL" IS NULL)
BEGIN
SELECT PROPUESTA.CASAS
INTO :new."CASASCAL"
FROM PROPUESTA WHERE PROPUESTA.IDPROPUESTA=new.IDPROPUESTA ;
END;
/
Error:
PL/SQL: ORA-00904: "NEW"."IDPROPUESTA": identifider not valid
Not sure why the accepted answer has been accepted as neither it nor the attached comments seem to address the obvious issue in the posted code.
In a trigger body we reference values in the inserted row with the :NEW code word. The posted code lacks the colon when it references the column in the WHERE clause. This is what is needed:
CREATE OR REPLACE TRIGGER "propuesta_casas"
BEFORE INSERT ON "PROPUESTA_TIENDA_BARRIO"
FOR EACH ROW
WHEN (new."CASASCAL" IS NULL)
BEGIN
SELECT PROPUESTA.CASAS
INTO :new."CASASCAL"
FROM PROPUESTA
WHERE PROPUESTA.IDPROPUESTA=:new.IDPROPUESTA ;
END;
/
Incidentally, watch out for using lower case in double quotes when creating objects.
By default all Oracle names are stored in the data dictionary in upper case, but the SQL statements are case insensitive. So the following two statments refer to the same object:
select * from emp
/
select * from EMP
/
However, if we create our object with a name in mixed case or lower case and put it in double quotes it is stored in the data dictionary with that exact case. This means we have to use that exact case whenever we reference the object, in double quotes. So if we created a table with all lower case ...
create table "emp" ...
... then this statement will fail:
select * from emp
/
It has to be
select * from "emp"
/
Of course if we already have a table called EMP then the first statement would have succeeded, if would just have selected from a different table.
In the case of triggers we generally don't refer to them by name. But we have to use the case whenever we look up the trigger in the data dictionary:
select status
from user_triggers
where trigger_name = 'propuesta_casas'
/
From what you described:
Try to recompile the trigger and see what happens...
A trigger becomes invalid if the base object (ex..table) becomes invalid or altered and the trigger refers to the affected table.