Oracle SQL: select from table with nested table - sql

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

Related

How to pass table column values to function

Table source contains integer column. Its values should be passed to Postgresql 12 function for selecting data from other table.
I tried to use array
CREATE OR REPLACE FUNCTION public.TestAddAssetTransactions(dokumnrs int[])
RETURNS int AS
$BODY$
with i1 as (
INSERT INTO bilkaib (dokumnr)
select dokumnr from dok where dokumnr in (select * from unnest(dokumnrs))
returning *
)
select count(*) from i1;
$BODY$ language sql;
create temp table bilkaib (dokumnr int ) on commit drop;
create temp table dok (dokumnr serial primary key ) on commit drop;
create temp table source (dokumnr int ) on commit drop;
insert into source values (1),(2);
select TestAddAssetTransactions( (select ARRAY[dokumnr] from source)::int[] )
but got error
ERROR: more than one row returned by a subquery used as an expression
How to pass single column values from table rows to function? Should array, table type or temp table used?
Using Postgresql 12+
You need to aggregate the ints in your function call. Otherwise you're just casting each value to a single-element array and they try to cast a column to an array of int.
select TestAddAssetTransactions( (select array_agg(dokumnr)::int[] from source) );
online demo

How to get list of cars with a specific ID of wheel?

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.

How fix problem "column reference "id" is ambiguous" in PostgreSQL function?

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
)

SQL : select from nested table oid

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;

Selecting and passing a record as a function argument

It may look like a duplicate of existing questions (e.g. This one) but they only deal with passing "new" arguments, not selecting rows from the database.
I have a table, for example:
CREATE TABLE my_table (
id bigserial NOT NULL,
name text,
CONSTRAINT my_table_pkey PRIMARY KEY (id)
);
And a function:
CREATE FUNCTION do_something(row_in my_table) RETURNS void AS
$$
BEGIN
-- does something
END;
$$
LANGUAGE plpgsql;
I would like to run it on data already existing in the database. It's no problem if I would like to use it from another PL/pgSQL stored procedure, for example:
-- ...
SELECT * INTO row_var FROM my_table WHERE id = 123; -- row_var is of type my_table%rowtype
PERFORM do_something(row_var);
-- ...
However, I have no idea how to do it using an "ordinary" query, e.g.
SELECT do_something(SELECT * FROM my_table WHERE id = 123);
ERROR: syntax error at or near "SELECT"
LINE 1: SELECT FROM do_something(SELECT * FROM my_table ...
Is there a way to execute such query?
You need to pass a scalar record to that function, this requires to enclose the actual select in another pair of parentheses:
SELECT do_something( (SELECT * FROM my_table WHERE id = 123) );
However the above will NOT work, because the function only expects a single column (a record of type my_table) whereas select * returns multiple columns (which is something different than a single record with multiple fields).
In order to return a record from the select you need to use the following syntax:
SELECT do_something( (SELECT my_table FROM my_table WHERE id = 123) );
Note that this might still fail if you don't make sure the select returns exactly one row.
If you want to apply the function to more than one row, you can do that like this:
select do_something(my_table)
from my_table;