Creating an XML document through SQL, but I get syntax error - sql

I have a small query to make an XML document:
Select XMLELEMENT(NAME movie,
XMLFOREST(Movie.name as title, year as year, rating as rating, plot_outline as plot,
XMLELEMENT(NAME actor, 'actor',
XMLAGG(
XMLELEMENT(NAME role, Acts.role )
),
XMLAGG(
XMLELEMENT(NAME person, Person.name))
)))
as result from Movie, Acts, Person
where Movie.mid = Acts.mid
and Acts.pid = Person.pid
But I get this error:
ERROR: unnamed XML element value must be a column reference
LINE 3: XMLELEMENT(NAME actor, 'actor',
^
This was supposed to be my expected result in XML:
<movie>
<title>Godfather, The</title>
<year>1972</year>
<rating>9.0</rating>
<plot>A Mafia boss' son, previously uninvolved in the business, takes over when his father is critically wounded in a mob hit.</plot>
<actor>
<role>Don Vito Corleone</role>
<person>Robert De Niro</person>
</actor>
<actor>
<role>Someone else</role>
<person>Someone else</person>
</actor>
</movie>
How do I get rid of this error message?

1) You can omit "name" word in xmlelement. xmlelment(name "name"... ) = xmlelment("name"...).
2) unnamed XML element value must be a column reference - that error is raise by xmlforest function.
xmlforest( col1, col2 as "TEST") - works fine
xmlforest(col1,xmlelement("TEST")) - throws error should be xmlforest(col1,xmlelement("TEST") as "xxx" )
3) XMLELEMENT(NAME actor, 'actor' you don need this. If i understand your query. You try to concatenate two xmlagg into one xmlelement. To do this use xmlconcat(xmlagg(..),xmlagg(..))
4) Finall query.
select xmlelement(
movie
, xmlforest(Movie.name as title
, year as year
, rating as rating
, plot_outline as plot
, xmlconcat(xmlagg(xmlelement(role, Acts.role)), xmlagg(xmlelement(person, Person.name))) as "actor"))
as result
from Movie, Acts, Person
where Movie.mid = Acts.mid and Acts.pid = Person.pid
You also have to add proper group by clause to it. Because it raise another exception. ORA-00937: not a single-group group function

Related

SQLite - problem with "near « ) » : syntax error"

I try here since i didn't find anything anywhere else.
I have a query which has been check by my colleagues and "teachers", but the error remains:
" near « ) » : syntax error".
The (last) query is the following one:
WITH valeur_par_ville AS
(
SELECT dep_code, com_code, AVG(valeur_fonciere) as valeur
FROM vente
JOIN bien ON bien.bien_id = vente.bien_id
JOIN commune ON commune.com_id = bien.com_id
WHERE dep_code IN (6,13,33,59,69)
GROUP BY dep_code, com_id
)
SELECT dep_code AS "Département", com_id AS "Commune", round(valeur,1) AS "Prix moyen"
FROM(
SELECT dep_code, com_nom, valeur_fonciere,
rank() OVER (PARTITION BY dep_code ORDER BY valeur_fonciere DESC) AS
rang
FROM valeur_par_ville) AS result
WHERE rang <= 3
I hope you can help me on this, because it becomes "black magic" to me!
Thanks.
I tried different ways to reach a result, but the same thing keeps going... I Checked all my data tables, updated SQLite (so PARTITION BY works on it now), reboot, checked the query little by little... No idea where it comes from.
Others colleagues (we are kind of students) managed to have a valid result with their own queries.
But for me:
" near « ) » : syntax error".
The error is coming from a different part of the code. I added CREATE TABLE statements to be able to run your code and it's failing differently.
CREATE TABLE vente(dep_code, com_code, valeur_fonciere, bien_id);
CREATE TABLE bien(bien_id, com_id);
CREATE TABLE commune(com_id);
-- your code here
The error:
Parse error near line 4: ambiguous column name: com_id
RE dep_code IN (6,13,33,59,69) GROUP BY dep_code, com_id ) SELECT dep_code AS
error here ---^
After prefixing it with a table name, there's another bunch of errors, e.g.
arse error near line 4: no such column: com_nom
(valeur,1) AS "Prix moyen" FROM( SELECT dep_code, com_nom, valeur_fonciere, ra
error here ---^
Parse error near line 4: no such column: valeur_fonciere
) AS "Prix moyen" FROM( SELECT dep_code, com_nom, valeur_fonciere, rank() OVER
error here ---^
etc.

Spatial Query Postgis

I have a polygon city and polygon data that I import into PostgreSQL, PostGIS. These intersect with cities. The first thing I need to do is to print the id from the city table to the other table, but while doing this, it needs to get the id of the city where the polygon is located. I tried a few functions to do this but got an error. Can you help me design the SQL command line?
update maden_polygon set objectid = maden_polygon.ilce_id
from (SELECT maden_polygon.ilce_id as id ,ankara_ilce.objectid as ilce_id
FROM maden_polygon , ankara_ilce
WHERE st_intersects(maden_polygon.geom, ankara_ilce.geom)) as maden_polygon
where maden_polygon.ilce_id = anakara_ilce.object_id
(ERROR: table name "maden_polygon" specified more than once )
What I want to do is to print the objectid column in the ankara_ilce table to the mine_polygon ilce_id table.
While doing this,
Write the object_id of which mine is within the boundaries of which county.
SELECT
maden_polygon.ilce_id as id ,
ankara_ilce.objectid as ad ,
ankara_ilce.adi as adi
from maden_polygon , ankara_ilce
where St_intersects(ankara_ilce.geom , maden_polygon.geom ) as sorgu
where maden_polygon.id = sorgu.id ;
ERROR: syntax error at or near "as"
LINE 6: ...ntersects(ankara_ilce.geom , maden_polygon.geom ) as sorgu
I think the query is a simple as this:
UPDATE maden_polygon set objectid = ilce_id
FROM ankara_ilce
WHERE st_intersects(maden_polygon.geom, ankara_ilce.geom)
BUT - note that the st_intersects can return multiple records per maden_polygon if your polygons overlap, and that might give you inconsistent results. You could try using st_contains instead (being aware that some records might not update that way). OR, you could match on the centroid of the one polygon e.g.
UPDATE maden_polygon set objectid = ilce_id
FROM ankara_ilce
WHERE st_within(st_centroid(maden_polygon.geom), ankara_ilce.geom)
Good luck!

SQL replace function error while using it to replace one string

I have event table in which there are two fields named as sport, event_name .
This was values such as:
{sport:"Athletic"; event_name:"Athletic 100 meter"}
What I want is to use replace function to replace the string in event_name that matches string in sport with nothing.
so the final output will be such :
{sport:"Athletic"; event_name:"100 meter"}
And I was also joined it with other table so only ID that are to be replace are also present in other table
so I used in this way in following code. But it should an error : "Expected item: < result-column > " . Thank you
SELECT
ae.id ,
ae.city AS event_city,
ae.sport,
REPLACE(ae.event,ae.sport,' ') AS event_name ,
FROM
athlete_events ae
inner join
players_personalinfo pp on
pp.id=ae.id
You need to define the table aliases:
SELECT ae.id AS event_id, ae.city AS event_city, ae.sport,
REPLACE(ae.event, ae.sport, ' ') AS event_name ,
ae.event
FROM athlete_events ae JOIN
players_personalinfo pp
ON pp.id = ae.id;
I would also advise you to trim the result:
TRIM(REPLACE(ae.event, ae.sport, ' ')) AS event_name,
This will remove leading and trailing spaces.
The REPLACE function is case sensitive. Try to check the data to make sure that the capitalization of each is the same.
The prior answers work, but you need to modify one of the field names in your query. In your description, you mentioned the field name is "event_name", but in your query, you reference just "event" (ae.event).
Also, I'm a little surprised that an event_id would join to a player's profile id. Seems a bit odd.
At any rate, I confirmed this SQL works in both postgres and oracle databases...
SELECT
ae.id AS event_id,
ae.city AS event_city,
ae.sport,
ae.event_name as event_name_original
REPLACE(ae.event_name,ae.sport,' ') AS event_name_kinda_ugly,
TRIM(REPLACE(ae.event_name,ae.sport,' ')) AS event_name_clean
FROM
athlete_events ae
inner join
players_personalinfo pp on pp.id=ae.id

Getting error "Only one expression can be specified in the select list..."

I am trying to add a column to a view with the following code:
SELECT ';' + CONTEXT as DriverNotes,
(STUFF((SELECT CustomerID FROM Notes E2 WHERE E2.CustomerID IN (Notes.CustomerID)
FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(5)'),1,0,'')) as CustomerID FROM NOTES
On it's own it works just fine. When I run it within a View however, I get the following error:
"Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
I realize that the code here is trying to call two columns and that is what is giving me the error, but I only want one, and that would be CONTEXT. I need this to correlate with Notes.CustomerID but without the column appearing in the query.
I am still quite new to this, so any help would be greatly appreciated.
Check this query. I think this is what you want :
SELECT Notes.CustomerId,
STUFF(
(SELECT ';' + CONTEXT FROM Notes E2
WHERE E2.CustomerId = Notes.CustomerId
FOR XML PATH ('')), 1, 1, ''
) DriverNotes
FROM Notes /*Probably it should be Customer table */
GROUP BY Notes.CustomerId

How can I call a db2 function and have it return multiple xml record data?

In SQL, I need to create xml code that looks like this:
<Phone>
<PhoneTypeCode tc="12">Mobile</PhoneTypeCode>
<Area>801</Area>
<DialNumber>9996666</DialNumber>
</Phone>
<Phone>
<PhoneTypeCode tc="2">Business</PhoneTypeCode>
<Area>801</Area>
<DialNumber>1113333</DialNumber>
</Phone>
When I run this sql, I correctly get two rows of data, as I would expect:
select
xmlelement(
Name "Phone",
xmlelement(
name "PhoneTypeCode",
xmlattributes(
trim(p1.phtype) as "tc"
),
trim(p1.desc)
),
xmlelement(name "AreaCode", p1.area),
xmlelement(name "DialNumber", p1.phone)
) as xml
from phone as p1 where p1.entityid = 256285;
These are the two rows of data I get back, exactly as I expected:
<Phone><PhoneTypeCode tc="12">Mobile</PhoneTypeCode><AreaCode>351</AreaCode> <DialNumber>4443333</DialNumber></Phone>
<Phone><PhoneTypeCode tc="2">Business</PhoneTypeCode><AreaCode>351</AreaCode><DialNumber>3911111</DialNumber></Phone>
However, when I try putting this same code in a function and call this function, I get this error:
SQL State: 21000
Vendor Code: -811
Message: [SQL0811] Result of SELECT more than one row. Cause . . . . . : The result table of a SELECT INTO statement, a subquery, or a subselect of a SET statement contains more than one row. The error type is 2. If the error type is 1 then a SELECT INTO statement attempted to return more than one row. If the error type is 2 then a subselect of a basic predicate has produced more than one row. Only one row is allowed. Recovery . . . : Change the selection so that only one result row is returned and then try the request again. The DECLARE CURSOR, OPEN, and FETCH statements must be used to process more than one result row. For a subquery the IN, EXISTS, ANY or ALL predicates can be used to process more than one result row. If one row was expected, there may be data errors, such as duplicate rows, that are causing more than one row to be returned.
**How can I fix this function so that it will return all rows of data as one block of xml code as I expect?
CREATE or replace FUNCTION xml_entity_phones (
#Entity_ID bigint)
RETURNS xml
LANGUAGE SQL
NOT DETERMINISTIC
reads SQL DATA
RETURNS NULL ON NULL INPUT
NO EXTERNAL ACTION
ALLOW PARALLEL
NOT FENCED
begin
return (
select
xmlelement(
Name "Phone",
xmlelement(
name "PhoneTypeCode",
xmlattributes(
trim(p.phtype) as "tc"
),
trim(p.desc)
),
xmlelement(name "AreaCode", p.area),
xmlelement(name "DialNumber", p.phone)
) as xml
from phone p where p.entityid = #entity_id
);
end
;
The procedure that calls this function, is building an xml file that includes different types of phones, which I wanted to build with the above function.
The end goal is to have an xml document (valid or not) that looks like this:
<TXLife>
<TXLifeRequest>
<OLife>
<Person>
<Phone>
<PhoneTypeCode tc="12">Mobile...
<Area...
<DialNumber...
</Phone>
<Phone>
<PhoneTypeCode tc="2">Business...
<Area...
<DialNumber...
</Phone>
...
I was hoping to build the entire phone section xml with a function call like: xml_entity_phones(bigint(e.entityid)).
OK, I changed the function to look like this with xmlagg():
begin
return (
select
xmlagg(
xmlelement(
Name "Phone",
xmlelement(
name "PhoneTypeCode",
xmlattributes(
trim(p.phtype) as "tc"
),
trim(p.desc)
),
xmlelement(name "AreaCode", p.area),
xmlelement(name "DialNumber", p.phone)
)
) as xml
from phone p
where p.entityid = #entity_id
);
end
But now when I call the function with values(xml_entity_phones(256285));, I get ++++++++++++++ as a result. And when I call the procedure that calls this function, I get this error:
SQL State: 22023
Vendor Code: -802
Message: [SQL0802] Data conversion or data mapping error. Cause . . . . . : Error type 10 has occurred 10 -- User-defined function returned a mapping error.
I did notice that when I include an extra element of Phones using xmlagg as suggested in a couple of answers below, that it does return the xmlagg() result successfully. However I can't have that extra element of Phones because it goes against the standard I need to adhere to.
Is there a way to return the xmlagg without the extra layer?
This is where you would use XMLAGG():
begin
return (
select
xmlelement(name "Phones", xmlagg(
xmlelement(
Name "Phone",
xmlelement(
name "PhoneTypeCode",
xmlattributes(
trim(p.phtype) as "tc"
),
trim(p.desc)
),
xmlelement(name "AreaCode", p.area),
xmlelement(name "DialNumber", p.phone)
)
)) as xml
from phone p where p.entityid = #entity_id
);
end
Obviously, I don't have your data but this simple example shows that the approach works:
$ db2 "create or replace function t () returns xml language sql begin \
return (select xmlagg(xmlelement(name \"tab\", tabname )) from syscat.tables \
where tabname like '%AUTH%' and tabschema = 'SYSCAT'); end"
DB20000I The SQL command completed successfully.
$ db2 "values t()"
1
----------------------------------------------------------------------------
<tab>COLAUTH</tab><tab>DBAUTH</tab><tab>INDEXAUTH</tab><tab>LIBRARYAUTH</tab>
<tab>MODULEAUTH</tab><tab>PACKAGEAUTH</tab><tab>PASSTHRUAUTH</tab><tab>ROLEAUTH
</tab><tab>ROUTINEAUTH</tab><tab>SCHEMAAUTH</tab><tab>SEQUENCEAUTH</tab>tab>
SURROGATEAUTHIDS </tab><tab>TABAUTH</tab><tab>TBSPACEAUTH</tab><tab>
VARIABLEAUTH</tab><tab>WORKLOADAUTH</tab><tab>XSROBJECTAUTH</tab>
1 record(s) selected.
When you issue a SQL select, you are retrieving a resultset (in some way a cursor). What you have is not a XML, it is a resultset that has two XML documents, or two rows. A XML document has just one parent, here you have two parents (phone)
You can retrieve a cursor like the one you have via a Stored Procedure.
create procedure x ()
P1:BEGIN
DECLARE cursor1 CURSOR WITH RETURN TO CLIENT FOR
xmlelement(
Name "Phone",
...
xmlelement(name "DialNumber", p1.phone)
) as xml
from phone as p1 where p1.entityid = 256285;
open cursor1;
END P1;