I'm sure all table names are ok. I want to get the list of players of each team.
public List<Speler> getSpelersPerPloeg(int ploegID)
{
List<Speler> spelersLijst = new List<Speler>();
connection.Open();
OleDbCommand command = new OleDbCommand("select * from proj1Speler inner join proj1Ploeg on proj1Speler.ploegID = proj1Ploeg.ploegID where proj1Ploeg.ploegID = #ploegID", connection);
command.Parameters.Add(new OleDbParameter("#ploegID", ploegID));
OleDbDataReader dataReader = command.ExecuteReader();
while (dataReader.Read())
{
spelersLijst.Add(new Speler((int)dataReader["spelerID"], dataReader["spelerNaam"].ToString(), (int)dataReader["ploegID"], dataReader["ploegNaam"].ToString(), (int)dataReader["spelerTypeID"]));
}
dataReader.Close();
connection.Close();
return spelersLijst;
}
It trows the error with ploegID on this line " spelersLijst.Add(new Speler((...", any ideas?
And the funny thing is with sql server it works without any problem, maybe my relations in Acces are wrong?
You are joining the two tables using the *, in this way fields from both tables are returned from your query.
But what happens when you have two fields with the same name from the two different tables in the same query? Some automatic renaming occurs, the tablename is added to the two identical field names to disambiguate the column name.
So when you try to use the simple name (without the table name) you get the error. I bet that the culprit is the "ploegID" field that appears in both tables.
I suggest to return just the field names really required by your code
OleDbCommand command = new OleDbCommand(#"select ps.spelerID, ps.spelerNaam,
pp.ploegID, pp.ploegNaam, ps.spelerTypeID
from proj1Speler ps
inner join proj1Ploeg pp
on ps.ploegID = pp.ploegID
where pp.ploegID = #ploegID", connection);
command.Parameters.Add(new OleDbParameter("#ploegID", ploegID));
OleDbDataReader dataReader = command.ExecuteReader();
(Note, I am not really sure about what field is contained in which table, this is just to get the idea)
Related
System.Data.SqlClient.SqlException: 'Ambiguous column name
'SchoolID'.'
I need to select a SchoolName == SchoolID and an AcademicYear from two combo-boxes that are found in two database tables School-Info and School_AcademicYear
Also SchoolID in School_AcademicYear is Foreign Key and its Primary Key in School_Info, I am using inner join to join these two tables but an error is occuring
Ambiguous column name 'SchoolID'
con.Open();
adp = new SqlDataAdapter("SELECT AcademicYearID,AcademicYear,SchoolID FROM School_AcademicYear INNER JOIN School_Info ON School_AcademicYear.AcademicYearID = School_Info.SchoolID where School_AcademicYear.AcademicYearID = '" + AcademicYearID + "'", con);
dt = new DataTable();
adp.Fill(dt);
dataGridViewSchoolNMergeAcYear.DataSource = dt;
con.Close();
If you join two tables that contain columns with the same name and you refer to one of these columns in the SELECT list, then you need to specify from which table are you getting the values. So to solve this problem let's start using some alias for the table names. Using the alias in front of the column's name correctly identify the columns source table.
While at it, I have also changed your string concatenation to a parameterized query. It is a lot better because it avoids parsing errors and a well known security problem called Sql Injection
using(SqlConnection con = new SqlConnection(.......))
{
string cmdText = #"SELECT a.AcademicYearID,a.AcademicYear,i.SchoolID
FROM School_AcademicYear a INNER JOIN School_Info i
ON a.AcademicYearID = i.SchoolID
WHERE a.AcademicYearID = #id";
con.Open();
adp = new SqlDataAdapter(cmdText, con);
adp.SelectCommand.Parameters.Add("#id", SqlDbType.Int).Value = AcademicYearID;
dt = new DataTable();
adp.Fill(dt);
dataGridViewSchoolNMergeAcYear.DataSource = dt;
}
To be complete this answer introduces also the using statement around the disposable connection object. In this way the connection is closed and disposed when the code exits the using block. Note that I suppose that AcademicYearID is a number and not a string so, the parameter is of type SqlDbType.Int instead of NVarChar.
You have multiple columns in those tables with name SchoolID.
You have to specify the column name, because sql cannot know which one you want. Example: School_Info.SchoolID
adp = new SqlDataAdapter(`
SELECT AcademicYearID,AcademicYear,School_Info.SchoolID
FROM School_AcademicYear
INNER JOIN School_Info ON School_AcademicYear.AcademicYearID = School_Info.SchoolID
where School_AcademicYear.AcademicYearID = '` + AcademicYearID + "'", con);
Currently working on a small tool for the company I am working at which shall handle the database. I have several classes handling various SQL functions, but whenever I try to put specific data from the database into a datagridview I get the Exception.
SQL function:
public class OUsersDB
{
SqlConnection conn = new SqlConnection("Connection Information");
public SqlDataReader Select()
{
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT au.ApplicationId, au.UserId, au.UserName, au.MobileAlias, au.LastActivityDate, au.Name, sms.number, am.email FROM aspnet_users AS au " +
" JOIN aspnet_membership AS am ON au.userid=am.userid " +
" JOIN smsphonebooks AS sms ON au.name=sms.name";
SqlDataReader ur = cmd.ExecuteReader();
return ur;
}
}
Winform datagrid function
public void Usersdb()
{
OUsersDB oudb = new OUsersDB();
SqlDataReader ur = oudb.Select();
myDataUsers.Rows.Clear();
while (ur.Read())
{
object[] objUsers = {
ur["au_ApplicationId"].ToString(),
ur["au_UserId"].ToString(),
ur["au_UserName"].ToString(),
ur["au_MobileAlias"].ToString(),
ur["au_LastActivityDate"].ToString(),
ur["au_Name"].ToString(),
ur["au_Phone"].ToString(),
ur["au_Email"].ToString(), };
myDataUsers.Rows.Add(objUsers);
conn.Close();
}
I have a similar sql function and object array futher up in the code which loads just fine, but once reaching this part I get the Exception on the
ur["au_ApplicationId"].ToString(),
It simply says
System.IndexOutOfRangeException: 'au_ApplicationId'
Change the obj to read the columns without the alias. You use aliases only to reference the columns in the query, but the output of the query won't have the aliases.
while (ur.Read())
{
object[] objUsers = {
ur["ApplicationId"].ToString(),
ur["UserId"].ToString(),
ur["UserName"].ToString(),
ur["MobileAlias"].ToString(),
ur["LastActivityDate"].ToString(),
ur["Name"].ToString(),
ur["Phone"].ToString(),
ur["Email"].ToString(), };
myDataUsers.Rows.Add(objUsers);
conn.Close();
}
Check if you get ANY object, maybe you get nothing at all.
You can try this:
https://stackoverflow.com/a/8656011/8512753
or remove the table aliases
ur["au_ApplicationId"].ToString(),
becomes
ur["ApplicationId"].ToString(),
and try assigning concrete values to the columns returned in your SQL
SELECT ApplicationId = au.ApplicationId, ...
Regarding the IndexOutOfRangeException, that's due to trying to access a column that doesn't exist in the reader. Not sure why you're prefixing columns with "au_" when the SELECT statement is not doing this.
I would use SqlDataAdapter instead and add add this method to OUsersDB.
public void FillTable(DataTable table)
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT au.ApplicationId, au.UserId, au.UserName, au.MobileAlias, au.LastActivityDate, au.Name, sms.number, am.email FROM aspnet_users AS au " +
" JOIN aspnet_membership AS am ON au.userid=am.userid " +
" JOIN smsphonebooks AS sms ON au.name=sms.name";
using(var adapter = new SqlDataAdapter(cmd))
adapter.Fill(table)
}
Change calling code to:
public void Usersdb()
{
OUsersDB oudb = new OUsersDB();
myDataUsers.Rows.Clear();
oudb.FillTable(myDataUsers);
}
Or here's a simple fix, instead. Change your SELECT statement to alias column names as the code is expecting.
SELECT au.ApplicationId as au_ApplicationId, au.UserId as au_UserId, au.UserName as au_UserName,
au.MobileAlias as au_MobileAlias, au.LastActivityDate as au_LastActivity, au.Name as au_Name,
sms.number as au_Phone, am.email as au_Email -- REST OF QUERY UNCHANGED
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)
How to check if my table is empty from C#?
I have something like:
public MySqlConnection con;
public MySqlCommand cmd;
con = new MySqlConnection(GetConnectionString());
con.Open();
cmd = new MySqlCommand("SELECT * FROM data;", con);
Or I don't need to call SELECT statement?
You can use COUNT(*) with no WHERE close and see if exactly how many rows exist with the result.
Or you can do a SELECT (id) FROM tablename with no WHERE clause and if no rows are returned then the table is empty.
I'll give you an example in C# good luck
public bool checkEmptyTable(){
try
{
MySql.Data.MySqlClient.MySqlCommand com = new MySql.Data.MySqlClient.MySqlCommand();
conn = new MySql.Data.MySqlClient.MySqlConnection("YOUR CONNECTION");
com.Connection = conn;
com.CommandText = "SELECT COUNT(*) from data";
int result = int.Parse(com.ExecuteScalar().ToString());
return result == 0; // if result equals zero, then the table is empty
}
finally
{
conn.Close();
}
}
If 'data' might be a big table you would be better with this (where pkdata is your primary key field)
SELECT COUNT(*) FROM data WHERE pkdata = (SELECT pkdata FROM data LIMIT 1);
This will run very quickly whether you have 0 rows in 'data' or millions of rows. Using SELECT with no WHERE or ORDER BY means it just pulls the first row available, LIMIT 1 stops it getting more than 1.
Maybe something to look for if you have a program that ran very quickly six months ago but now runs like a dog in treacle!
SELECT COUNT(*)
FROM table
WHERE `col_name` IS NOT NULL
I am using C# to write a method that returns the following information about a table:
column names, column types, column sizes, foreign keys.
Can someone point me in the right direction on how to accomplish this ?
This really depends on how you communicate with your database. If you are using LinqToSQL or another similar ORM this would be pretty easy but if you want to get these values via a query I'd suggest you use the INFORMATION_SCHEMA views as these are fast and easy to query.
e.g.
select * from information_schema.columns where table_name = 'mytable'
To get the FK and Schema you should be able to use:
DA.FillSchema()
DS.Table("Name").PrimaryKey
OR calling sp_fkey using the method demonstrated below
Code Snippet from AND Another Link
private void LoanSchema()
{
private List<String> tablesList = new List<String>();
private Dictionary<String, String> columnsDictionary = new Dictionary<String, String>();
string connectionString = "Integrated Security=SSPI;" +
"Persist Security Info = False;Initial Catalog=Northwind;" +
"Data Source = localhost";
SqlConnection connection = new SqlConnection();
connection.ConnectionString = connectionString;
connection.Open();
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "exec sp_tables";
command.CommandType = CommandType.Text;
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
tablesList.Add(reader["TABLE_NAME"].ToString());
}
reader.Close();
command.CommandText = "exec sp_columns #table_name = '" +
tablesList[0] + "'";
command.CommandType = CommandType.Text;
reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
columnsDictionary.Add(reader["COLUMN_NAME"].ToString(), reader["TYPE_NAME"].ToString());
}
}
You can use the SqlDataAdapter.FillSchema() method.
Alternatively you can use the SqlDataAdapter.Fill() method after setting the MissingSchemaAction property of the SqlDataAdapter to AddWithKey. But if you only want the schema you must ensure that your query returns no rows. This can be accomplished by adding a statement like WHERE 1=2 to your query.
If you are using MS SQL Server then You should definately have a look at SMO namespace (server management objects).
There are objects which You can use in .net responsible for all kinds of things in a database (including but not limited to tables, columns, constraints etc.)
I think you need the System.Data.DataTable class:
http://msdn.microsoft.com/en-us/library/system.data.datatable.aspx