I tried to select from the nested table but an error message displayed "ORA-00933: SQL command not properly ended"
This is the request of selecttion
select b.NomPlayer from table (select t.players from Team t where t.IdTeam=1) as p;
And this is the code witch I created the player_type and team_type
CREATE OR REPLACE TYPE Player_Type AS OBJECT ( Num_Licence NUMBER, NomPlayer VARCHAR2(30)) ;
CREATE TYPE PlayersNT AS TABLE OF ref Player_Type ;
CREATE TYPE Team_Type AS OBJECT ( IdTeam NUMBER, TeamName VARCHAR2(30), Players PlayersNT ) ;
CREATE TABLE Player OF Player_Type ;
CREATE TABLE Team OF Team_Type
NESTED TABLE Players STORE AS PlayersTab ;
Remove the AS in the FROM clause. Unlike other databases, Oracle only allows AS in the SELECT clause.
select * from table(select t.players from Team t where t.IdTeam=1) p;
Related
I'm given quite a huge table My_Table and a user-defined collection Picture_Arr as an input usually having 5-10 rows declared as:
TYPE Picture_Rec IS RECORD (
seq_no NUMBER,
task_seq NUMBER);
TYPE Picture_Arr IS TABLE OF Picture_Rec;
In MS SQL I would normally write something like:
DECLARE #Picture_Arr TABLE (seq_no INT, task_seq INT)
SELECT M.*
FROM My_Table M
INNER JOIN #Picture_Arr A
ON M.seq_no = A.seq_no AND M.task_seq = A.task_seq
But I can't get my head around how to re-write the same code in Oracle as Picture_Arr is not a table. As some tutorials state that I could've looped through My_Table and compare keys, but is it efficient in Oracle or is there another way of doing that?
Perhaps this is what you are looking for. It is a bit complicated to understand what is the desired output, and whether the data of the record is stored somewhere or not
create type Picture_Rec as object(
seq_no NUMBER,
task_seq NUMBER);
)
/
create type Picture_Tab as table of Picture_Rec
/
create or replace function get_picture_list
return Picture_Tab
is
l_pic Picture_Tab;
begin
select Picture_Rec ( seqno, taskseq )
bulk collect into l_pic
from your_table; -- the table you have these records
return l_pic;
end;
/
Then you run
SELECT M.*
FROM My_Table M
JOIN TABLE ( get_picture_list() ) p
ON M.seq_no = p.seq_no AND M.task_seq = p.task_seq
I have the following code snippet :
CREATE TYPE ModeleRoue (nom VARCHAR2(10) );
CREATE TYPE ModeleMoteur (nom VARCHAR2(10) );
CREATE TYPE ModeleVoiture (nom VARCHAR2(50) );
CREATE TABLE EnsModeleVoiture OF ModeleVoiture;
CREATE TABLE EnsModeleMoteur OF ModeleMoteur;
CREATE TABLE EnsModeleRoue OF ModeleRoue;
CREATE TYPE ModeleRoue (nom VARCHAR2(10) );
CREATE TYPE ModeleMoteur (nom VARCHAR2(10) );
CREATE TYPE ModeleVoiture (nom VARCHAR2(50) );
CREATE TABLE EnsModeleVoiture OF ModeleVoiture;
CREATE TABLE EnsModeleMoteur OF ModeleMoteur;
CREATE TABLE EnsModeleRoue OF ModeleRoue;
I want to get the Voitures having number of Roue = 554 :
SELECT v.numero FROM ensvoiture v
WHERE EXISTS (SELECT * FROM v.roues r WHERE r.numero=554);
What is the difference of using the table in the EXISTS subquery directly in the WHERE clause?
SELECT v.numero FROM ensvoiture v
WHERE v.roues.numero =554;
The right way to write your first query would be:
SELECT v.numero FROM ensvoiture v
WHERE EXISTS (SELECT * FROM v.roues r WHERE r.numero=v.numero and r.numero=554);
This query, written this way, is doubtfully usefull, because it seems that you want to filter your ensvoiture table for those numbers equal to 554. Therefore, the exists would be unnecesary and you could use just your second query.
SELECT v.* FROM ensvoiture v
WHERE v.numero =554;
This doesn't mean that both queries will return the same data, because if there is no any r.numero=554, your first query will return nothing. The second one will keep returning data even whether the roues table doesn't have any numero=554.
In PostgreSQL database I have 2 table: services and services_organizations_relationship. Each organization has a specific list of services.
My next function need to create new records in services table, then create relationship between services and organizations and finally return list of all new created services.
CREATE OR REPLACE FUNCTION test (
SERVICE_NAME_ARRAY VARCHAR[],
ACTIVE_ARRAY BOOLEAN[],
DESCRIPTION_ARRAY TEXT[],
ORGANIZATION_ID_ARRAY INT[]
) RETURNS TABLE (
ID UUID,
NAME VARCHAR,
ACTIVE BOOLEAN,
DESCRIPTION TEXT
) AS $$
BEGIN
RETURN QUERY
WITH RESULTS AS (
INSERT INTO SERVICES (NAME, ACTIVE, DESCRIPTION)
SELECT
UNNEST(ARRAY[SERVICE_NAME_ARRAY]) AS NAME,
UNNEST(ARRAY[ACTIVE_ARRAY]) AS ACTICE,
UNNEST(ARRAY[DESCRIPTION_ARRAY]) AS DESCRIPTION
RETURNING ID, NAME, ACTIVE, DESCRIPTION
),
GENERATE_SERVICES_ORGANIZATIONS_RELATIONSHIP AS
(
INSERT INTO SERVICES_ORGANIZATIONS_RELATIONSHIP (SERVICE_ID, ORGANIZATION_ID)
SELECT
UNNEST(ARRAY_AGG(ID)) AS SERVICE_ID,
UNNEST(ARRAY[ORGANIZATION_ID_ARRAY]) AS ORGANIZATION_ID
FROM RESULTS
ON CONFLICT ON CONSTRAINT SERVICES_ORGANIZATIONS_RELATIONSHIP_UNIQUE_KEY DO NOTHING
)
SELECT ID, NAME, ACTIVE, DESCRIPTION FROM RESULTS;
END;
$$ LANGUAGE plpgsql;
When I call this function:
SELECT * FROM test(ARRAY['SLOT', 'JTC'], ARRAY[TRUE, FALSE], ARRAY['SLOT', 'JTC'], ARRAY[30572, 30573]);
I see such error:
SQL Error [42702]: ERROR: column reference "id" is ambiguous
Details: It could refer to either a PL/pgSQL variable or a table column.
Where: PL/pgSQL function test(character varying[],boolean[],text[],integer[]) line 3 at RETURN QUERY
How to fix this problem?
The final line of the query should be
SELECT result.id, result.name,... FROM result
To avoid such collisions, you can use different names for the columns in the RETURNS TABLE clause (which are variables) and the columns in the queries (e.g. by using aliases).
Try this
GENERATE_SERVICES_ORGANIZATIONS_RELATIONSHIP AS
(
INSERT INTO SERVICES_ORGANIZATIONS_RELATIONSHIP (SERVICE_ID, ORGANIZATION_ID)
SELECT
UNNEST(ARRAY_AGG(t1.ID)) AS SERVICE_ID,
UNNEST(ARRAY[ORGANIZATION_ID_ARRAY]) AS ORGANIZATION_ID
FROM RESULTS t1
ON CONFLICT ON CONSTRAINT SERVICES_ORGANIZATIONS_RELATIONSHIP_UNIQUE_KEY DO NOTHING
)
I'm new to working with PL/pgSQL, and I'm attempting to create a function that will either find the ID of an existing row, or will insert a new row if it is not found, and return the new ID.
The query contained in the function below works fine on its own, and the function gets created fine. However, when I try to run it, I get an error stating "ERROR: column reference "id" is ambiguous". Can anybody identify my problem, or suggest a more appropriate way to do this?
create or replace function sp_get_insert_company(
in company_name varchar(100)
)
returns table (id int)
as $$
begin
with s as (
select
id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning id
)
select id
from i
union all
select id
from s;
end;
$$ language plpgsql;
This is how I call the function:
select sp_get_insert_company('TEST')
And this is the error that I get:
SQL Error [42702]: ERROR: column reference "id" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column.
Where: PL/pgSQL function sp_get_insert_company(character varying) line 3 at SQL statement
As the messages says, id is in there twice. Once in the queries, once in the table definition of the return type. Somehow this clashes.
Try qualifying the column expressions, everywhere.
...
with s as (
select
companies.id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning companies.id
)
select i.id
from i
union all
select s.id
from s;
...
By qualifying the column expression the DBMS does no longer confuse id of a table with the id in the return type definition.
The next problem will be, that your SELECT has no target. It will tell you to do a PERFORM instead. But I assume you want to return the results. Change the body to
...
RETURN QUERY (
with s as (
select
companies.id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning companies.id
)
select i.id
from i
union all
select s.id
from s);
...
to do so.
In the function you display there is no need for returns table (id int). It's supposed to always return exactly one integer ID. Simplify to RETURNS int. This also makes ERROR: column reference "id" is ambiguous go away, since we implicitly removed the OUT parameter id (visible in the whole function block).
How to return result of a SELECT inside a function in PostgreSQL?
There is also no need for LANGUAGE plpgsql. Could simply be LANGUAGE sql, then you wouldn't need to add RETURNS QUERY, either. So:
CREATE OR REPLACE FUNCTION sp_get_insert_company(_company_name text)
RETURNS int AS
$func$
WITH s as (
select c.id -- still good style to table-qualify all columns
from companies c
where c.name = _company_name
),
i as (
insert into companies (name)
select _company_name
where not exists (select 1 from s)
returning id
)
select s.id from s
union all
select i.id from i
LIMIT 1; -- to optimize performance
$func$ LANGUAGE sql;
Except that it still suffers from concurrency issues. Find a proper solution for your undisclosed version of Postgres in this closely related answer:
Is SELECT or INSERT in a function prone to race conditions?
I wonder how can i make select statement from table which have a typed column ?
Type of this column is defined as:
create or replace TYPE "MYCOL" as table of MYTYPE;
create or replace TYPE "MYTYPE" as OBJECT
( myid Number, myname Varchar2);
UPD1
Table is defined as
CREATE TABLE "T_TABLE"
( "ID" NUMBER NOT NULL ENABLE, "NAME" "MYCOL" )
If i select this column with select * from T_TABLE i will get this not informative result:
1, MYSCHEMA.MYCOL([MYSCHEMA.MYTYPE],[MYSCHEMA.MYTYPE])
I want just to unwrap this types.
Try it like this:
select t."ID", tt.myid, tt.myname
from "T_TABLE" t, table(t."NAME") tt;
Here is a sqlfiddle demo