I have a C# windows forms application and I'm working with a database too.
I have 3 tables: Players, Tournaments and TournamentsPlayers.
I will only show 2 tables in the form, the Tournaments and the Players tables. The Tournaments table has a column which is a checkbox and I want to show in the Players table only the players from the tournaments which I checked the box.
When the application starts I have a foreach statement which check all the tournaments, so at first all the players should show in the Players table, but no player is shown.
My code is:
private void ShowPlayersForSelectedTournaments()
{
string query =
"SELECT a.Name, a.Id FROM Players a,TournamentPlayers b WHERE a.Id=b.TournamentId AND b.TournamentId=#TournamentId";
using (Connection = new SqlConnection(ConnectionString))
using (SqlCommand command = new SqlCommand(query, Connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
foreach (DataGridViewRow row in TournamentsTable.Rows)
{
if (row.Cells.Count > 0 && bool.Parse(row.Cells[0].Value.ToString()))
{
command.Parameters.AddWithValue("#TournamentId", row.Cells[1].Value);
DataTable tournamentPlayersList = new DataTable();
adapter.Fill(tournamentPlayersList);
PlayersTable.DataSource = tournamentPlayersList;
break;
}
}
}
}
I have tried a simple select and all is working, but with this sql syntax it doesn't seems to work.
I have tried with another similar mysql syntax, like:
string query = "SELECT a.Name FROM Players a INNER JOIN TournamentPlayers b ON a.Id=b.TournamentId WHERE b.TournamentId=#TournamentId";
But still nothing shows in the Players table.
What am I doing wrong? Is there something wrong with my mysql syntax or my code?
This is your query:
SELECT a.Name, a.Id
FROM Players a,TournamentPlayers b
WHERE a.Id=b.TournamentId AND b.TournamentId=#TournamentId;
It has multiple problems. This should work:
SELECT p.Name, p.Id
FROM Players p JOIN
TournamentPlayers tp
ON tp.playerId = p.id
WHERE tp.TournamentId = #TournamentId;
Notes:
Never use commas in the FROM clause. Always use proper, explicit JOIN syntax.
Use abbreviations for the table names, so the query makes sense when read.
FIx the join condition between the tables, to match on the player. It is highly unlikely that a player has the same id as a tournament and also played in that tournament. Possible, but unlikely.
Related
In my database i have three tables. One For employs where i keep their names, ids, salary... In the second one named Project i keep id, location, name. in the third one named WorksOn i keep the id from employs and the id from project. In my Asp .Net web site in gridview i need to display the employee's name and the name of the project that he is working.
string connect =
WebConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
SqlConnection con = new SqlConnection(connect);
try
{
con.Open();
}
catch (Exception err)
{
string error = err.Message;
con.Close();
}
SqlCommand command = new SqlCommand();
command.Connection = con;
SqlDataReader reader;
command.CommandText = "SELECT * FROM WorksON ";
reader= command.ExecuteReader();
In data source in gridview if i choose to display the values from WorksOn table it shows the id from employs and the id from project but what i need is to show the names on the employs and project.
I know that i need to do something with dataset but i don't know who.
Your SQL command must JOIN the related tables. Something like:
SELECT * FROM WorksOn JOIN Employee on WorksOn.EmployeeId = Employee.Id
Note that you should not SELECT "*" (all columns). You should only SELECT those columns that are necessary to your data view for performance.
On your SQL command, you don't mention anything about Employs. You need to use a JOIN SQL command in order to get both the employee name and the company name.
And instead of using "SELECT * FROM...", consider using the columns name instead, because you're not trying to get all the columns display. And it will help us understand the name of the columns to further help you.
Use a JOIN query like this:
SELECT project.projectName, employee.Name
FROM (worksOn
INNER JOIN employee
ON (worksOn.employeeId = employee.employeeId))
INNER JOIN project
ON (project.projectId = employee.employeeId)
AND (worksOn.projectId = project.projectId)
I'm creating a small c# application linked to an online MySql database to further my knowledge on these 2 things.
In my database I have 2 tables "user" and "dvd" and they are build as this:
user: ID, GEBRUIKERSNAAM, PASWOORD
dvd: ID, TITLE,DUUR,USERID,...
What I'm trying to do now is take a colum from each table and display them in a dataGridView.
The colum's that I want are from table dvd: TITEL and from table user: GEBRUIKERSNAAM.
A dvd is linked to a user (One user many dvd's), using the ID from table user and the foreign key USERID from table dvd.
As a result I want to show 2 colums in my dataGridView one for the dvd's titel and the other kekst to the first for the owner of the dvd (witch is the GEBRUIKRSNAAM colum).
To do this I wrote the following code:
SELECT 'TITEL', dvd.TITEL
FROM xxx.dvd
UNION ALL
SELECT 'GEBRUIKERSNAAM', user.GEBRUIKERSNAAM
FROM xxx.user
INNER JOIN xxx.dvd ON user.ID = dvd.USERID
WHERE user.ID = xxx.dvd.USERID;
This however gives me 2 problems:
If I use it directly on my database (using the SQL tab from
phpMyAdmin) it works, but merges the 2 colums into one what I don't want. I think the problem here is the "Union All" piece, but I don't know how else to do this.
If I try to use this code using my c# application I get the following error: "Functionality SelectCommand.Connection is not initialized". I know the problem is somewere in this query because if I try it with a different query my code works like it is supposed to. (It fills the dataGridView).
try
{
MySqlCommand SelectCommand = new MySqlCommand("SELECT TITEL FROM xxx.dvd UNION ALL SELECT GEBRUIKERSNAAM FROM xxx.user INNER JOIN xxx.dvd ON user.ID = dvd.USERID WHERE user.ID = xxx.dvd.USERID;");
myConn.Open();
MySqlDataAdapter sda = new MySqlDataAdapter();
sda.SelectCommand = SelectCommand;
DataTable dbdataset = new DataTable();
sda.Fill(dbdataset);
BindingSource bSource = new BindingSource();
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
myConn.Close();
Any help,tips or correct ways of doing something (best practice) on this problem are welcome
Thanks
I'm not totally clear on what your goal is, but maybe some part of this will help you:
SELECT U.GEBRUIKERSNAAM, D.TITLE
FROM dvd D JOIN user U ON D.USERID = U.ID
WHERE D.ID = 1
This will take the dvd table, and for each entry look up the user whose ID matches D.USERID. From that merged row, it will select the U.GEBRUIKERSNAAM and D.TITLE, but only results where the dvd ID is 1.
Please comment if there are further questions. I hope I understood your goal correctly. It may be easier if you gave me an example of what your desired output should look like & have me write the query.
If I understand your problem correctly then you need to display 2 columns where you to show wht user has hired the DVD for that you should use the query:
select d.TITLE, u.GEBRUIKERSNAAM
from dvd d
Inner join user u
ON u.ID = d.USERID
I am using parameterized select queries in conjunction with my program and as a whole, it works except when I try to join tables.
Here is a small excerpt what I have done:
using (MySqlCommand cmd = new MySqlCommand(paramQuery.ToSql(), connection)) {
/*
paramQuery.ToSql() equals:
"Select tableOne.ID, tableOne.Department, tableTwo.Name
From tableOne, tableTwo
Where tableOne.ID = #param0"
*/
for (int index = 0; index < paramQuery.Parameters().Count; index++)
cmd.Parameters.AddWithValue(paramQuery.Parameters().ElementAt(index).Key,
paramQuery.Parameters().ElementAt(index).Value);
/*
paramQuery.Parameters().ElementAt(index).Key = "#param0"
paramQuery.Parameters().ElementAt(index).Value = "tableTwo.ID"
*/
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
// Do stuff
}
}
One of the tables that I am try to join will retrieve everyone in tableTwo with the same ID for all. Is there something that I am doing wrong here?
try this:
Select tableOne.ID, tableOne.Department, tableTwo.Name
From tableOne join tableTwo
on tableOne.ID=tableTwo.ID
Where tableOne.ID = #param0
as you understand tableOne.ID=tableTwo.ID is the name of the columns which you joining tables on. At your current example I do not see how it can work.
There is also Left join and right join which serves each to a different purposes.
Here is some example to look how it works: http://dev.mysql.com/doc/refman/5.0/en/join.html
I tried to add a new row to a Table in an SQL DB, but I had a problem :
dynamic sql generation is not supported against multiple base tables
this is the code I tried :
private MyClass myClass = new MyClass();
private SqlDataAdapter adapter;
private SqlDataAdapter adapter2;
private void GestionCollections_Load(object sender, EventArgs e)
{
adapter = new SqlDataAdapter("select Id_Collection ID, Libelle_Collection Collection,Libelle_Editeur Editeur from Collection_ left join Editeur on Id_Editeur = Collection_.Id_Editeur_Editeur", myClass.cnx);
adapter.Fill(myClass.ds, "Collection_");
adapter2 = new SqlDataAdapter("Select Id_Editeur ID,Libelle_Editeur Editeur from Editeur", myClass.cnx);
adapter2.Fill(myClass.ds, "Editeur");
}
private void AjouterBarButton_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
String newKeyWordCollectionName = ajoutCollection.KeyWordCollectionName;
String newKeyWordAEditeurName = ajoutCollection.KeyWordEditeurName;
DataRow row = myClass.ds.Tables["Collection_"].NewRow();
row[1] = newKeyWordCollectionName;
foreach(var myRow in myClass.ds.Tables["Editeur"].AsEnumerable())
{
if (newKeyWordAEditeurName == myRow[1] as String)
row[2] = (int)myRow[0];
}
myClass.ds.Tables["Collection_"].Rows.Add(row);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
adapter.Update(myClass.ds, "Collection_");
}
Change your select query and add distinct with inner join.
For example there are two query from which you can understand that what I want to tell you
Wrong query
select iop.pob_id, iop.pob_product_id, iop.pob_qty, iop.pob_unit_id
, iop.pob_rate, iop.pob_value, iop.pob_fiscalyear_id
, **p.product_desc** as orderBy from inv_product_open_balc iop
left join inv_product p on iop.pob_product_id = p.product_id
where p.product_desc like 'Air Freshner%' and iop.pob_fiscalyear_id = 3
Correct query
select distinct iop.pob_id, iop.pob_product_id, iop.pob_qty
, iop.pob_unit_id, iop.pob_rate, iop.pob_value, iop.pob_fiscalyear_id
, **(select Product_desc from** inv_product p where p.product_id = iop.pob_product_id )as orderBy
from inv_product_open_balc iop
inner join inv_product p on iop.pob_product_id = p.product_id
where p.product_desc like 'Air Freshner%' and iop.pob_fiscalyear_id = 3
You can't use an SqlCommandBuilder here:
Automatically generates single-table commands that are used to reconcile changes made to a DataSet with...
The key words here being "single-table". It has no way to reverse engineer from the SELECT statement how a specific update should be applied (e.g. if you NULL all of the columns from the right side of a left join, should it delete the row, or set each column to null.
You need to author appropriate Insert, Update and Delete commands on the SqlDataAdapter.
With SqlCommandBuilder you can generate CRUD operation on entity
Requirement of use is to define Select command before inserting , and include in the select command your primary Key.
Link : http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlcommandbuilder(v=vs.80).aspx
MSDN Definition : Automatically generate Transact-SQL statements to update single table
Nota : In your Update selectCommand, you defined left join query, and so you can create left join query, replace this query with just select.
Add DISTINCT in your select statement with inner join.
This will solve the issue.
like Select Distinct Employee.Ecode, .........
I have a function:
public static List<T> EntityCache<T>(this System.Linq.IQueryable<T> q, ObjectContext dc, string CacheId)
{
try
{
List<T> objCache = (List<T>)System.Web.HttpRuntime.Cache.Get(CacheId);
string connStr = (dc.Connection as System.Data.EntityClient.EntityConnection).StoreConnection.ConnectionString;
if (objCache == null)
{
ObjectQuery<T> productQuery = q as ObjectQuery<T>;
string sqlCmd = productQuery.ToTraceString();
using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr))
{
conn.Open();
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sqlCmd, conn))
{
string NotificationTable = q.ElementType.Name;
System.Web.Caching.SqlCacheDependency sqldep = new System.Web.Caching.SqlCacheDependency(cmd);
cmd.ExecuteNonQuery();
objCache = q.ToList();
System.Web.HttpRuntime.Cache.Insert(CacheId, objCache, sqldep);
}
}
}
return objCache;
}
catch (Exception ex)
{
throw ex;
}
}
q can be a table, view or a procedure.
What i want is to find the underlying tables associated with a view or a procedure.
like if q is a join of tow tables i want to get the name of both the tables and finally
execute like:
If there are tw0 tables say A and B
Then i need to make Aggregate Dependency like:
string sqlCmd1 = string.Empty;
string sqlCmd2 = string.Empty;
using (testEntities ctx1 = new testEntities())
{
sqlCmd1 = ((System.Data.Objects.ObjectQuery)(from p in ctx1.A select p)).ToTraceString();
sqlCmd2 = ((System.Data.Objects.ObjectQuery)(from p in ctx1.B select p)).ToTraceString();
}
System.Data.SqlClient.SqlCommand cmd1 = new System.Data.SqlClient.SqlCommand(sqlCmd1, conn);
System.Data.SqlClient.SqlCommand cmd2 = new System.Data.SqlClient.SqlCommand(sqlCmd2, conn);
System.Web.Caching.SqlCacheDependency
dep1 = new System.Web.Caching.SqlCacheDependency(cmd1),
dep2 = new System.Web.Caching.SqlCacheDependency(cmd2);
System.Web.Caching.AggregateCacheDependency aggDep = new System.Web.Caching.AggregateCacheDependency();
aggDep.Add(dep1, dep2);
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
then the query i want to execute is
select * from A;
select * from B;
This i am using for SqlCacheDependency using Linq to Entity.
It works well for views when i hardcode the underlying tables but now i want the code automatically check for the underlying tables
and execute nonquery like
cmd1.ExecuteNonQuery();
cmd2.ExecuteNonQuery();
and make aggregate dependencies.
Any help is appreciated.
Thanks.
You must use database level tools to find which database objects your views or stored procedures depends on (but it also means you must know their full names in the database). For example SQL server offers sp_depends system stored procedure to track dependencies. This can be quite complicated because dependencies can have multiple levels (procedure can be dependent on view, view can be dependent on another view, etc.).
Be aware that advanced EF mapping also allows writing SQL directly to EDMX and in such case you will have to parse ToTraceString to find database objects.
I have found a solution for the problem i have posted.
There is a query that is valid for sql server 2005 onward.
We need to pass the name of the object and it will return us the name of the tables on which it depends
Example:
The name of the View is say AllProducts_Active_Inactive
;WITH CTE AS (SELECT o.name
, o.type_desc
, p.name
, p.type_desc as B
, p.object_id
FROM sys.sql_dependencies d
INNER JOIN sys.objects o
ON d.object_id = o.object_id
INNER JOIN sys.objects p
ON d.referenced_major_id = p.object_id
where o.name = 'AllProducts_Active_Inactive'
UNION ALL
SELECT o.name
, o.type_desc
, p.name
, p.type_desc as B
, p.[object_id]
FROM sys.sql_dependencies d
INNER JOIN CTE o
ON d.object_id = o.object_id
INNER JOIN sys.objects p
ON d.referenced_major_id = p.object_id
where o.name = 'AllProducts_Active_Inactive'
)
SELECT DISTINCT * FROM [CTE]
where B = 'USER_TABLE'
This post is the modified answer of the question i have posted on the website:
http://ask.sqlservercentral.com/questions/81318/find-the-underlying-tables-assocaited-with-a-view-or-a-stored-procedure-in-sql-server
What i changed is added the line where B = 'USER_TABLE'
Which means only those dependencies are returned who are tables.
And the seconds thing is added a WHERE clause so that a specific object is found.
Thanks