I created sequence for manager first.
CREATE SEQUENCE manager_seq
START WITH 200
MAXVALUE 299
CYCLE
CACHE 10;
Then I inserted some values using .NEXTVAL
INSERT INTO manager
VALUES (manager_seq.NEXTVAL,'')
When I try to query with where statement it says ORA-00936: missing expression
select * from manager where number = 201;
Why it isn't working with sequnce numbers how can I use them?
Column name can't be number, that's a reserved word - reserved for datatype. For example:
SQL> create table manager (id number,
2 number number); --> this
number number)
*
ERROR at line 2:
ORA-00904: : invalid identifier
Therefore, post table description (so that we could suggest what to do) or use valid query.
If you use a reserved word as an identifier then you need to quote it everywhere you use it. So, if you have the table:
CREATE TABLE manager (
"NUMBER" NUMBER,
something VARCHAR2(10)
);
Then you insert rows:
INSERT INTO manager VALUES (manager_seq.NEXTVAL,'');
INSERT INTO manager VALUES (manager_seq.NEXTVAL,'');
Then, if you use an unquoted identifier:
select * from manager where number = 201;
You get the error:
ORA-00936: missing expression
But, if you use a quoted identifier with the correct case then you can query the table:
select * from manager where "NUMBER" = 201;
Which outputs:
NUMBER
SOMETHING
201
null
Note: In Oracle, '' and NULL are identical.
db<>fiddle here
Related
I am trying to create a parameterless procedure that is used to take columns from a table and do some modifications to it and paste it into another table. But I am getting the following errors:
Procedure DEMO compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
4/2 PL/SQL: SQL Statement ignored
8/10 PLS-00403: expression 'NET.NETSALARY' cannot be used as an INTO-target of a SELECT/FETCH statement
8/24 PL/SQL: ORA-00904: : invalid identifier
Errors: check compiler log
My code used for this in sql is :
create or replace procedure "DEMO"
as
begin
case when comm is null then 0.9*grosssalary
when comm<500 then 0.85*grosssalary
else 0.8*grosssalary end
into net.netsalary from (select salary+comm as grossSalary,comm from
employee) ;
end ;
/
I am trying to insert the data into column netsalary of table net.
Please mention where did I go wrong?
Thanking you in advance.
Syntax is
CREATE OR REPLACE PROCEDURE demo
AS
BEGIN
INSERT INTO net (netsalary)
SELECT CASE
WHEN comm IS NULL THEN 0.9 * grosssalary
WHEN comm < 500 THEN 0.85 * grosssalary
ELSE 0.8 * grosssalary
END
FROM (SELECT salary + comm AS grossSalary, comm FROM employee);
END;
but it won't do much good. You're inserting as many rows as there are in the employee table, but ALL you insert is netsalary value - you don't even know who it belongs to.
Without knowing tables' description, it is difficult to guess what you really want to do.
insert? Probably employee number (or whatever that column name is) is missing
update? That's completely different command
create or replace function idxF(status IN char) return char deterministic is
retVal CHAR(1);
begin
dbms_output.put_line('P');
retVal:=CASE status
when 'P' then 'P'
when 'H' then 'H'
else null
end ;
return retVal;
end idxF;
create index setIndexOnStatus on ORDER(idXF(STATUS));
SQL Error: ORA-00904: "IDXF": invalid identifier
STATUS is a CHAR(1) column in ORDER table.
Why is the compiler saying that IDXF is an invalid identifier?
ORDER is a reserved word in Oracle (part of ORDER BY clause) so you shouldn't use it as a name for your table.
Technically, you can escape a reserved word with double quotes:
create index setIndexOnStatus on "ORDER"(idXF(STATUS));
Probably, this table was created like this in a first place.
This approach is extremely problematic because you'll need to escape every query to this table and it's not always possible, especially with auto-generated queries.
So, don't go this way, rename the table instead.
P.S. I couldn't reproduce ORA-00904 on this query. Invalid table name leads to ORA-00903: invalid table name. Escaped query works fine for me. If you still have ORA-00904 error then you'll need to build a reproducible example to demonstrate your problem (i.e. include CREATE TABLE statement and specify the Oracle version).
Given this table:
create table test (
name text primary key
);
I need to write a plpgsql function with a variable name that collides with the primary key name, which I must use in a on conflict clause:
create or replace function func(
name text -- this variable name...
) returns void language plpgsql as
$$
begin
insert into test (name) values (name)
on conflict (name) do update -- ...conflicts with this line
set name = func.name;
end;
$$;
This compiles, but then throws an ambiguous column reference:
select * from func('one');
ERROR: column reference "name" is ambiguous
LINE 2: on conflict (name) do update
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: insert into test (name) values (name)
on conflict (name) do update
set name = func.name
CONTEXT: PL/pgSQL function func(text) line 3 at SQL statement
I tried specifying the full column name as on conflict (test.name) which does not compile, or ((test.name)) which compiles:
create or replace function func(
name text
) returns void language plpgsql as
$$
begin
insert into test (name) values (name)
on conflict ((test.name)) do -- this fails too
update set name = func.name;
end;
$$;
But it fails as well:
select * from func('two');
ERROR: invalid reference to FROM-clause entry for table "test"
LINE 2: on conflict ((test.name)) do
^
HINT: There is an entry for table "test", but it cannot be referenced from this part of the query.
QUERY: insert into test (name) values (name)
on conflict ((test.name)) do
update set name = func.name
CONTEXT: PL/pgSQL function func(text) line 3 at SQL statement
Is there a solution?
Edit: I found a workaround:
on conflict on constraint test_pkey do update
where test_pkey is the table name plus _pkey. I don't know how reliable this is though. I'd still like to specify the column name instead.
to start with, name is a bad name for both variable and attribute. When you have both, code won't look good. with that in mind, you can "prefix" variable with labeled block (in example below <<fn>>``), and setvariable_conflict` to give preference to column name, see code below:
t=# create or replace function func(
name text
) returns void language plpgsql as
$$
#variable_conflict use_column
<<fn>>
declare name text :='blah';
begin
insert into test (name) values (name)
on conflict (name) do -- this no longer fails
update set name = fn.name;
end;
$$;
t=# insert into test select 'b';
INSERT 0 1
Time: 8.076 ms
t=# select func('b');
func
------
(1 row)
Time: 6.117 ms
t=# select * from test;
name
------
b
blah
(2 rows)
https://www.postgresql.org/docs/current/static/plpgsql-implementation.html#PLPGSQL-VAR-SUBST
By default, PL/pgSQL will report an error if a name in a SQL statement
could refer to either a variable or a table column. You can fix such a
problem by renaming the variable or column, or by qualifying the
ambiguous reference, or by telling PL/pgSQL which interpretation to
prefer.
and further - basically the whole link is about it.
And yet - after demonstrating how particular task this can be easily done with plpgsql, I still quote namual:
The simplest solution is to rename the variable or column. A common
coding rule is to use a different naming convention for PL/pgSQL
variables than you use for column names. For example, if you
consistently name function variables v_something while none of your
column names start with v_, no conflicts will occur.
The ON CONFLICT... syntax (as documented here) uses a unique constraint to determine if the row conflicts. You can specify this unique constraint either by listing the columns it contains (at which point Postgres "infers" the correct index to use) or by naming the constraint directly.
In your case, the unique constraint being used is the primary key constraint implicitly created during your CREATE TABLE statement. This will have a name given to it by the DBMS, unless you specify one directly; so you will need to either look up the name the DBMS has given it (and be aware that this may change if you recreate the schema later), or name it explicitly when you create the table using the syntax CONSTRAINT pk_some_name PRIMARY KEY.
You would then specify the clause as ON CONFLICT ON CONSTRAINT pk_some_name DO ... (note no brackets around the constraint name).
(Alternatively, of course, you could change your function to use an unambiguous parameter name; personally, I think it's good practice to use a prefix like p_ or in_ rather than handling conflicts on a case-by-case basis.)
I'm trying to create a procedure where the input is lname from table Employee and output is sal and average from table Information. Both outputs are numbers and average is a decimal number. This is what I have so far.
CREATE OR REPLACE PACKAGE getSalAvgPack IS PROCEDURE getSalAvg
(name IN Employee.lname%TYPE,
pSal OUT NUMBER,
pAvg OUT NUMBER);
END;
.
/
The package compiles fine.
CREATE OR REPLACE PACKAGE BODY getSalAvgPack IS PROCEDURE getSalAvg
(name IN Employee.lname%TYPE,
pSal OUT NUMBER,
pAvg OUT NUMBER)
IS
BEGIN
SELECT Information.sal, Information.average
INTO pSal, pAvg
FROM Information
WHERE Information.eid=Employee.eid AND name=lname;
END;
END;
.
/
When I try to compile the package body I get these errors
PL/SQL: SQL Statement ignored (for line 7, column 2)
PL/SQL: ORA-00904: "LNAME": invalid identifier
You need to join in the Employee table:
SELECT Information.sal, Information.average
INTO pSal, pAvg
FROM Information join
Employee
on Information.eid=Employee.eid
WHERE name=lname;
It appears that you are missing a join
SELECT Information.sal, Information.average
INTO pSal, pAvg
FROM Information
JOIN Employee ON (Information.eid = Employee.eid)
WHERE name = Employee.lname;
As a general principle, I would strongly suggest using a naming convention for your parameters that differentiates them from columns in your tables. If name is a column in either table that you're joining, your predicate will compare the Employee.lname against that column rather than using the name parameter from your procedure. A common convention is to prefix all parameters with p_ so that your query becomes
SELECT Information.sal, Information.average
INTO p_Sal, p_Avg
FROM Information
JOIN Employee ON (Information.eid = Employee.eid)
WHERE p_name = Employee.lname;
I am running a basic query that retrieves rows based on basic conditional clauses, nothing complex. This works fine:
<cfquery name="courses" datasource="banner">
SELECT *
FROM tjucatalog
WHERE (course_status = 'Active')
AND CONCAT(subject,course_no) IN (#PreserveSingleQuotes(courselist)#)
AND term IN ('Fall 2012')
AND ((end_date > #now()#) OR (course_meeting_info IS NOT NULL))
ORDER BY TYear, TSort, DayNum, start_date, time, title
</cfquery>
However, when I remove the "AND term IN" line from the query, it fails.
<cfquery name="courses" datasource="banner">
SELECT *
FROM tjucatalog
WHERE (course_status = 'Active')
AND CONCAT(subject,course_no) IN (#PreserveSingleQuotes(courselist)#)
AND ((end_date > #now()#) OR (course_meeting_info IS NOT NULL))
ORDER BY TYear, TSort, DayNum, start_date, time, title
</cfquery>
The error I get is: ORA-06502: PL/SQL: numeric or value error: character string buffer too small ORA-06512: at "BANINST1.TJUCATALOG_PACK", line 519
Is this maybe a view that requires the field 'term' to be included, or is there something else at play here I'm entirely unaware of?
This appears to be an error in a package that's being called under the hood, possibly from a view. You're querying against tjucatalog, and it seems plausible that is a view where one of the returned columns is actually a functional call.
It isn't necessarily the term column that's the problem. By removing that condition, more rows will be returned, and the function is being called against a column value from a row that isn't there when the condition is in place. But it could be any column in one of those now-visible rows.
As a simple and contrived example of what might be happening:
create table t42 (id number, foo varchar2(20));
insert into t42 (id, foo) values (1, 'Short');
insert into t42 (id, foo) values (2, 'More than 10');
create package p42 as
function func(p_id in number) return varchar2;
end p42;
/
create package body p42 as
function func(p_id in number) return varchar2 is
l_bar varchar2(10);
begin
select foo into l_bar from t42 where id = p_id;
return l_bar;
end func;
end p42;
/
create view v42 as select id, p42.func(id) as bar from t42;
So we have a table with two rows, one with a foo less than 10 characters, the other more than 10 characters. We have a (silly) package function that takes an id value, looks up foo, and returns it. And a view that uses that function.
This works:
select * from v42 where id = 1;
ID BAR
---------- --------------------
1 Short
But removing the condition causes it to fail:
select * from v42;
ERROR:
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at "SCOTT.P42", line 5
Line 5 of my package body is select foo into l_bar from t42 where id = p_id; and the problem is that I've declare l_bar as varchar2(10), which is too small for the foo value for id=2. I should have declared it as varchar2(20), or even better t42.foo%TYPE.
To see what your problematic function is doing, look at the source code, which you can get from the database (if it isn't wrapped) if you don't have it available:
select line, text from all_source
where owner = 'BANINST1'
and name = 'TJUCATALOG_PACK'
and type = 'PACKAGE BODY'
order by line;
Our Oracle gurus returned and told us they had to change a field type from varchar2 (4000) to CLOB. The lack of the term field as a filter clause was a red herring error. I don't know which field specifically in the query needed to be increased for allowed length, but it works so I'm happy.