SELECT tbl_user.userid,
tbl_user.firstname,
tbl_user.lastname,
tbl_user.email,
tbl_user.created,
tbl_user.createdby,
tbl_organisation.organisationname
FROM tbl_user
INNER JOIN tbl_organisation
ON tbl_user.organisationid = tbl_organisation.organisationid
WHERE organisationid = #OrganisationID;
I am using this statement to do a databind. I am getting a error here.
Column 'OrganisationID' in where clause is ambiguous
What should I do is it wrong to name the OrganisationID in tbl_user same as tbl_organisation.
OrganisationID is a foreign key from tbl_Organisation
Since you have two columns with the same name on two different tables (and that's not a problem, it's even recommended on many cases), you must inform MySQL which one you want to filter by.
Add the table name (or alias, if you were using table aliases) before the column name. In your case, either
WHERE tbl_user.OrganisationID
or
WHERE tbl_Organisation.OrganisationID
should work.
You just need to indicate which table you are targeting with that statement, like "tbl_user.OrganisationID". Otherwise the engine doesn't know which OrganisationID you meant.
It is not wrong the have the same column names in two tables. In many (even most) cases, it is actually perferred.
Related
I have a query like this (simplified and anonymised):
SELECT
Department.id,
Department.name,
Department.manager_id,
Employee.name AS manager_name
FROM
Department
LEFT OUTER JOIN Employee
ON Department.manager_id = Employee.id;
The field Department.manager_id may be NULL. If it is non-NULL then it is guaranteed to be a valid id for precisely one row in the Employee table, so the OUTER JOIN is there just for the rows in the Department table where it is NULL.
Here is the problem: old instances of the database do not have this Department.manager_id column at all. In those cases, I would like the query to act as if the field did exist but was always NULL, so e.g. the manager_name field is returned as NULL. If the query only used the Department table then I could just use SELECT * and check for the column in my application, but the JOIN seems to make this impossible. I would prefer not to modify the database, partly so that I can load the database in read only mode. Can this be done just by clever adjustment of the query?
For completeness, here is an answer that does not require munging both possible schemas into one query (but still doesn't need you to actually do the schema migration):
Check for the schema version, and use that to determine which SELECT query to issue (i.e. with or without the manager_id column and JOIN) as a separate step. Here are a few possibilities to determine the schema version:
The ideal situation is that you already keep track of the schema by assigning version numbers to the schema and recording them in the database. Commonly this is done with either:
The user_version pragma.
A table called "Schema" or similar with one row containing the schema version number.
You can directly determine whether the column is present in the table. Two possibilities:
Use the table_info pragma to determine the list of columns in the table.
Use a simple SELECT * FROM Table LIMIT 1 and look at what columns are returned (this is probably better as it is independent of the database engine).
This seems to work:
SELECT
Dept.id,
Dept.name,
Dept.manager_id,
Employee.name AS manager_name
FROM
(SELECT *, NULL AS manager_id FROM Department) AS Dept
LEFT OUTER JOIN Employee
ON Dept.manager_id = Employee.id;
If the manager_id column is present in Department then it is used for the join, whereas if it is not then Dept.manager_id and Employee.name are both NULL.
If I swap the column order in the subquery:
(SELECT NULL AS manager_id, * FROM Department) AS Dept
then the Dept.manager_id and Employee.name are both NULL even if the Department.manager_id column exists, so it seems that Dept.manager_id refers to the first column in the Dept subquery that has that name. It would be good to find a reference in the SQLite documentation saying that this behaviour is guaranteed (or explicitly saying that it is not), but I can't find anything (e.g. in the SELECT or expression pages).
I haven't tried this with other database systems so I don't know if it will work with anything other than SQLite.
I have a simple query like this:
SELECT * FROM CUSTOMERS WHERE CUSTID LIKE '~' AND BANKNO LIKE '~'
The problem is, the customers-table might or might not contain the BANKNO column depending on circumstances I've no control over. If however BANKNO is not a column in CUSTOMERS, this query fails.
So my question is: it is possible to test if the BANKNO column exists and if so, to include it in the query and if not to exclude this column?
The query really has to be flexible.
A non-existent column in a SELECT to sqlite3 will always fail.
One option might be to put the "full" sql in a try block, and if it errors, execute the other sql.
Or, you could query PRAGMA table_info('CUSTOMERS') and interrogate the result to see if a column in question is in the database. Find the sqlite doc here https://www.sqlite.org/pragma.html#pragma_table_info.
I'm sure there are other options, but the bottom line is you need to know before the sql is executed that it contains only valid column names.
Is there a documentation/specification about Sqlite3 that would describe would is supposed to happen in the following case?
Take this query:
var cmd = new SqliteCommand("SELECT Items.*, Files.* FROM Items LEFT JOIN Files ON Files.strColName = Items.strColName");
Both Items and Files have a column name "strColName". If an entry exists in Files, it will be joined to the result, if not, it will be NULL.
Let's assume I always need the value of strColName, no matter if it is coming from Items or from Files. If I execute a reader:
var reader = cmd.ExecuteReader();
If there is a match in Files, reader["strColName"] will obviously contain the correct result because the value is set and it is the same in both tables. But if there wasn't a match in Files, will the NULL value of Files overwrite the non-NULL value of Items?
I'm really looking for some specification that defines how a Sqlite3 implementation has to deal with this case, so that I can trust either result.
SQLite has no problem returning multiple columns labelled with the same name.
However, the columns will always be returned in exactly the same order they are written in the SELECT statement.
So, when you are searching for "strColName", you will find the first one, from Items.
It is recommended to use explicit column names instead of * so that the order is clear, and you can access values by their column index, if needed (and you detect incompatible changes in the table structure).
I am trying to implement an idea where I have two sql tables in a database.
Table Info which has a field Nationality and the other Table Exclusion which has a field Keyword.
`Info.Nationality` `Exclusion.Keyword`
|British| |France|
|resteraunt de France| |Spanish|
|German|
|Flag Italian|
|Spanish rice|
|Italian pasta
|Irish beef|
In my web application I am creating a GridView4 and through a DataTable and SqlDataAdapter I am populating that GridView4 with the SQL command:
SELECT DISTINCT Info.Nationality WHERE Exclusion.Keyword NOT LIKE '%Spanish%'
That SQL statement retrieves all the distinct records in Info.Nationality which do not contain the word spanish.
What I am currently doing is that in the web app which is in vb.net I am adding two different GridViews, each have the data of each table which means that GridView2 has DISTINCT Info.Nationality and GridView3 has Exclusion.Keyword and then adding another GridView4 to display the results of the above SQL command.
The idea is to retrieve all the distinct records from Info.Nationlity which are not suppressed by the keyword constraints in Exclusion.keyword. So from the above mentioned Sql command the GridView4 will retrieve all the records which do not have the word "Spanish".
I am doing all of this in a nested for loop where in the first loop it takes each record (one by one) from Info.Nationality e.g.for each row As DataRow in Me.GridView2.Rows() and compare it with the second for loop which goes till the end of the Exclusion.Keyword which would be like For i=0 To Gridview3 - 1.
The problem is that in that sql statement I have to explicitly specify the word to compare. I tried adding the records of Exclusion.Keyword in a String and then replacing the Spanish Keyword In between the NOT LIKE with the name of the String which is Keywords and then assigning the name a parameter with cmd.parameter.addwithvalue(#String, Keywords). However this is not working, it is only comparing with the last record in the string and ignoring the first.
The idea behind all of this is to display all the records of Info.Nationality in GridView4 which do not contain the keywords in Exclusion.Keyword.
Is there an easier or more effecient way to do this? I was thinking of an Inner Join with a Like command but that is not my problem. My problem is that how can I compare each record one by one of Info.Nationlity with all the records in Exclusion.keyword and then retrieving the ones that do not match and discarding the ones that match.
Then in Gridview4 how can I edit the records without reflecting those changes or affecting in Info.Nationality but rather only Inserting to Exclusion.Keyword the changes.
SOLVED by adding ToString() after Text
In my asp.net web app, I tried this, but didn't work: (SOLVED)
`SELECT DISTINCT Nationality
FROM Info Where NOT EXISTS(SELECT * FROM Exclusion WHERE Info.Nationality LIKE '%' + #GridView +'%')`
`cmd.parameters.AddwithValue("#GridView", GridView3.Rows(i).Cells(0).Text.ToString())`
GridView3 Here has the Exclusion.Keywords data.
Would really appreciate your suggestions and thoughts around this.
You do not need to do this one-by-one, or "Row by agonizing row" as some DBAs are fond of describing this type of approach. There are lots of ways to write a query to only return the records from Info.nationality that do not match the exclusion keywords as a single expression.
My preference is to use the EXISTS clause and a correlated subquery:
SELECT Nationality
FROM Info I
WHERE NOT EXISTS(SELECT * FROM Exclusion WHERE I.Nationality LIKE '%' + Keyword + '%')
You can also express this as a left join.
SELECT I.Nationality
FROM Info I
LEFT OUTER JOIN Exclusion E
ON I.Nationality LIKE '%' + E.Keyword + '%'
WHERE E.Keyword IS NULL
The left join will return all the rows from info and insert nulls in the columns for Exclusion except where the join criteria matches. By filtering for only where those values are null, you can avoid the matches.
Maybe i should do this in C# but i have more then one row with linkId X. I would like to remove it but i am unsure how. In code i could just use a foreach from 0 to n and remove any found rows with a greater (or !=) id but thats in code. Is there a less difficult way of doing it using sqlite?
Assuming the table's name is tableName and there is a primary key field named id, the following sql would do it. I think the following SQL query is general enough and should be able to be executed under any database engine.
delete from tableName
where id not in (
select min(id) from tableName
group by linkId
)