I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)
Related
Using WSO2AM-2.1.0-update12 (carbon-apomgt tag v6.2.108) normally works well with mysql. We intend to switch the underlying database to Oracle DB (11g as far I know), looks simple.
Wen creating an API the apim throws an SQLException
ORA-00907: missing right parenthesis
we traced the exception to
org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO:7652
executing following query:
SELECT
A.SCOPE_ID, A.NAME, A.DISPLAY_NAME,
A.DESCRIPTION, C.SCOPE_BINDING
FROM
((IDN_OAUTH2_SCOPE AS A INNER JOIN AM_API_SCOPES AS B ON A.SCOPE_ID = B.SCOPE_ID)
INNER JOIN IDN_OAUTH2_SCOPE_BINDING AS C ON B.SCOPE_ID = C.SCOPE_ID )
WHERE B.API_ID = 1;
Running this query itself against the APIM database indeed reproduces the exception, so the code hasn't been properly tested. For some customizations we rather try to fix the code if possible than migrate to a newer version (where we have no ensurance the issue is fixed or our customizations will work)
I suspect the query as been not tested as at all and correct query may look like
SELECT
A.SCOPE_ID, A.NAME, A.DISPLAY_NAME,
A.DESCRIPTION, C.SCOPE_BINDING
FROM
IDN_OAUTH2_SCOPE A INNER JOIN AM_API_SCOPES B ON A.SCOPE_ID = B.SCOPE_ID
INNER JOIN IDN_OAUTH2_SCOPE_BINDING C ON B.SCOPE_ID = C.SCOPE_ID
WHERE B.API_ID = 1;
I'd like to validate and correct me if the query is syntactically and semantically not equivalent
Could you please try the following?
SELECT A.SCOPE_ID, A.NAME, A.DISPLAY_NAME, A.DESCRIPTION, C.SCOPE_BINDING FROM ((IDN_OAUTH2_SCOPE A INNER JOIN AM_API_SCOPES B ON A.SCOPE_ID = B.SCOPE_ID) INNER JOIN IDN_OAUTH2_SCOPE_BINDING C ON B.SCOPE_ID = C.SCOPE_ID ) WHERE B.API_ID = ?
You can find this corrected query in https://github.com/wso2/carbon-apimgt/blob/6.x/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java#L2068
I have this query where I am trying to introduce a non-static value into PERCENTILE_CONT:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
The error thrown is:
ORA-30497: Argument should be a constant or a function of expressions in GROUP BY.
30497. 00000 - "Argument should be a constant or a function of expressions in GROUP BY."
This is in a view, it was working fine when goalsASP.GOAL*.01 was .75 and I have a stored procedure where feeding a column as an argument works just fine so I'm kind of at a loss for what I'm doing wrong here.
Got it. It's not so much a problem of Percentile_Cont, it's a problem of correct grouping.
To troubleshoot I isolated goalsASP.GOAL
SELECT perf2.REVIEW_PERIOD
, goalsASP.GOAL
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD
Then it became obvious that I needed to also group by goalsASP.GOAL.
So, then, the answer is:
SELECT perf2.REVIEW_PERIOD
, PERCENTILE_CONT(goalsASP.GOAL*.01) WITHIN GROUP (ORDER BY AVG_AMT ASC) ast75
FROM repDB.TBL_PERFORMANCE perf2 JOIN
pz.CATEGORY C on perf2.DEPTCAT = C.id JOIN
repDB.TBL_GOALS_MATRIX goalsASP ON C.NAME = goalsASP.DIMENSION_Y
and perf2.REVIEW_PERIOD = goalsASP.SNAP_NAME
and goalsASP.DIMENSION_X = 'asp'
GROUP BY perf2.REVIEW_PERIOD,
goalsASP.GOAL
Kind of embarrassing that I didn't see that before, but tired eyes miss this stuff.
I am facing some issue while joining multiple tables in oracle.
Here are the table structs:
TName : custac
acno - FK (acno custacdetails)
acbal
bid
Tname : custacdetails
custid - FK (custid custdetails)
acno - PK
actype
Tname : custdetails
custid - PK
fname
lname
Tname : branchdetails
bid
bname
I want to view all customers acno, acbal, branchname, fname, lname whose custid is 11111 and actype is 'SA'
I am using this query but i am getting wrong result
select a.acno,c.fname,c.lname,b.bname,a.acbal
from branch_details b,
custac a,
custacdetails d,
custdetails c
where c.custid=11111
and a.acno=d.acno
and a.branchid=b.bid
and actype='SA';
As per Tony891206 saying, you'Re doing a cartesian product. To avoid it, you need to tell how to join both tables together.
d.custid = c.custid
As follows:
select a.acno,c.fname,c.lname,b.bname,a.acbal
from branch_details b,
custac a,
custacdetails d,
custdetails c
where d.custid = c.custid
and c.custid=11111
and a.acno=d.acno
and a.branchid=b.bid
and actype='SA';
All credit goes to Tony891206.
This being said, as stated by a_horse_with_no_name:
Another good example why using explicit JOIN operators is better than the (outdated) implicit join in the where clause: you can't forget the join condition.
So the correct query should be written as follows.
select a.acno, c.fname, c.lname, b.bname, a.acbal
from branch_details b
join custac a on a.bid = b.bid
join custacdetails d on d.acno = a.acno
join custdetails c on c.custid = d.custid
where c.custid = 11111
and d.actype = 'SA'
This last query makes the relationship between the tables glaringly obvious, and allows for room in the where clause to specify only filter criterion.
If you want to know more about SQL syntaxes, please visit the followings:
Bad habits to kick : using old-style JOINs
Why isn't SQL ANSI-92 standard better adopted over ANSI-89?
Join (SQL)
In short, you would have had better chances to solve your problem by yourself using the SQL-92 join syntax over the SQL-89 one, since you would have had no other choice than to ask yourself how your tables may get joined together while writing the join clauses.
In addition to it, some say that there is a slight improvement on the performance using SQL-92 syntax, which I personally doubt. Besides, I do evangelize SQL-92 join syntax for it is easier to read than the SQL-89.
When running a test with the following query, HSQLDB mistakes the table alias as a schema.
SELECT c.country_ml2country as CTRY_PK, c.name as CTRY_NAME,
l.name as LANGUAGE_NAME, l.code as LANGUAGE_CODE
FROM country_ml as c, language as l
WHERE c.language(+) = l.id and c.country_ml2country(+) = ?
ORDER BY l.name ASC;
Has anyone experienced this before? If "yes", then what is the fix?
Note that if I change FROM country_ml as c to FROM country_ml as bob, then the error message changes accordingly to invalid schema name: BOB.
The problem is the non-standard Oracle-style OUTER JOIN syntax, which is specific to Oracle and not supported by other SQL dialects.
WHERE c.language(+) = l.id and c.country_ml2country(+) = ?
You should use instead the following standard syntax, which Oracle also supports:
SELECT c.country_ml2country as CTRY_PK, c.name as CTRY_NAME,
l.name as LANGUAGE_NAME, l.code as LANGUAGE_CODE
FROM country_ml as c RIGHT OUTER JOIN language as l
ON c.language = l.id and c.country_ml2country = ?
ORDER BY l.name ASC
If I use a join, the Include() method is no longer working, eg:
from e in dc.Entities.Include("Properties")
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e
e.Properties is not loaded
Without the join, the Include() works
Lee
UPDATE: Actually I recently added another Tip that covers this, and provides an alternate probably better solution. The idea is to delay the use of Include() until the end of the query, see this for more information: Tip 22 - How to make include really include
There is known limitation in the Entity Framework when using Include().
Certain operations are just not supported with Include.
Looks like you may have run into one on those limitations, to work around this you should try something like this:
var results =
from e in dc.Entities //Notice no include
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select new {Entity = e, Properties = e.Properties};
This will bring back the Properties, and if the relationship between entity and Properties is a one to many (but not a many to many) you will find that each resulting anonymous type has the same values in:
anonType.Entity.Properties
anonType.Properties
This is a side-effect of a feature in the Entity Framework called relationship fixup.
See this Tip 1 in my EF Tips series for more information.
Try this:
var query = (ObjectQuery<Entities>)(from e in dc.Entities
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e)
return query.Include("Properties")
So what is the name of the navigation property on "Entity" which relates to "Item.Member" (i.e., is the other end of the navigation). You should be using this instead of the join. For example, if "entity" add a property called Member with the cardinality of 1 and Member had a property called Items with a cardinality of many, you could do this:
from e in dc.Entities.Include("Properties")
where e.Member.Items.Any(i => i.Collection.ID == collectionID)
select e
I'm guessing at the properties of your model here, but this should give you the general idea. In most cases, using join in LINQ to Entities is wrong, because it suggests that either your navigational properties are not set up correctly, or you are not using them.
So, I realise I am late to the party here, however I thought I'd add my findings. This should really be a comment on Alex James's post, but as I don't have the reputation it'll have to go here.
So my answer is: it doesn't seem to work at all as you would intend. Alex James gives two interesting solutions, however if you try them and check the SQL, it's horrible.
The example I was working on is:
var theRelease = from release in context.Releases
where release.Name == "Hello World"
select release;
var allProductionVersions = from prodVer in context.ProductionVersions
where prodVer.Status == 1
select prodVer;
var combined = (from release in theRelease
join p in allProductionVersions on release.Id equals p.ReleaseID
select release).Include(release => release.ProductionVersions);
var allProductionsForChosenRelease = combined.ToList();
This follows the simpler of the two examples. Without the include it produces the perfectly respectable sql:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Releases] AS [Extent1]
INNER JOIN [dbo].[ProductionVersions] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ReleaseID]
WHERE ('Hello World' = [Extent1].[Name]) AND (1 = [Extent2].[Status])
But with, OMG:
SELECT
[Project1].[Id1] AS [Id],
[Project1].[Id] AS [Id1],
[Project1].[Name] AS [Name],
[Project1].[C1] AS [C1],
[Project1].[Id2] AS [Id2],
[Project1].[Status] AS [Status],
[Project1].[ReleaseID] AS [ReleaseID]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent2].[Id] AS [Id1],
[Extent3].[Id] AS [Id2],
[Extent3].[Status] AS [Status],
[Extent3].[ReleaseID] AS [ReleaseID],
CASE WHEN ([Extent3].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM [dbo].[Releases] AS [Extent1]
INNER JOIN [dbo].[ProductionVersions] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ReleaseID]
LEFT OUTER JOIN [dbo].[ProductionVersions] AS [Extent3] ON [Extent1].[Id] = [Extent3].[ReleaseID]
WHERE ('Hello World' = [Extent1].[Name]) AND (1 = [Extent2].[Status])
) AS [Project1]
ORDER BY [Project1].[Id1] ASC, [Project1].[Id] ASC, [Project1].[C1] ASC
Total garbage. The key point to note here is the fact that it returns the outer joined version of the table which has not been limited by status=1.
This results in the WRONG data being returned:
Id Id1 Name C1 Id2 Status ReleaseID
2 1 Hello World 1 1 2 1
2 1 Hello World 1 2 1 1
Note that the status of 2 is being returned there, despite our restriction. It simply does not work.
If I have gone wrong somewhere, I would be delighted to find out, as this is making a mockery of Linq. I love the idea, but the execution doesn't seem to be usable at the moment.
Out of curiosity, I tried the LinqToSQL dbml rather than the LinqToEntities edmx that produced the mess above:
SELECT [t0].[Id], [t0].[Name], [t2].[Id] AS [Id2], [t2].[Status], [t2].[ReleaseID], (
SELECT COUNT(*)
FROM [dbo].[ProductionVersions] AS [t3]
WHERE [t3].[ReleaseID] = [t0].[Id]
) AS [value]
FROM [dbo].[Releases] AS [t0]
INNER JOIN [dbo].[ProductionVersions] AS [t1] ON [t0].[Id] = [t1].[ReleaseID]
LEFT OUTER JOIN [dbo].[ProductionVersions] AS [t2] ON [t2].[ReleaseID] = [t0].[Id]
WHERE ([t0].[Name] = #p0) AND ([t1].[Status] = #p1)
ORDER BY [t0].[Id], [t1].[Id], [t2].[Id]
Slightly more compact - weird count clause, but overall same total FAIL.
Has anybody actually ever used this stuff in a real business application? I'm really starting to wonder...
Please tell me I've missed something obvious, as I really want to like Linq!
Try the more verbose way to do more or less the same thing obtain the same results, but with more datacalls:
var mydata = from e in dc.Entities
join i in dc.Items
on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e;
foreach (Entity ent in mydata) {
if(!ent.Properties.IsLoaded) { ent.Properties.Load(); }
}
Do you still get the same (unexpected) result?
EDIT: Changed the first sentence, as it was incorrect. Thanks for the pointer comment!