Cleanest way to check if table exists - MySQL - c#

Working with C# and MySQL here (Visual Studio 12 and MySQL workbench 6.1).
This is what I have so far.
string strCheck = "SHOW TABLES LIKE \'emp\'";
MySqlCommand cmd = new MySqlCommand(strCheck, con);
cmd.Prepare();
if (cmd.ExecuteNonQuery() > 0)
{
Console.WriteLine("exists");
}
else
{
Console.WriteLine("does not");
}
I have seen many questions here (mostly related to PHP) but they don't seem to be working for me. Also, I don't want a solution where we check if the table has any rows, because the table can be empty, and what I want to know is whether it exists.
Thanks.

Try the following SELECT statement:
SELECT EXISTS(
SELECT
`TABLE_NAME`
FROM
`INFORMATION_SCHEMA`.`TABLES`
WHERE
(`TABLE_NAME` = 'emp')
AND
(`TABLE_SCHEMA` = 'mydb')
) as `is-exists`;

Related

INSERT statement not adding any data without throwing error

I am trying to add train objects to a database to hold their details for persistence.
I have it working so I can add the trains to a list. But when I try to set up an INSERT statement to add the train objects details to a database. nothing is added to my database when i check it after. I don't get any errors thrown anywhere either.
Can anyone see anything wrong with my INSERT statement?
//If the type combobox has Express selected
if (cbxType.Text == "Express")
{
//Create a new train with its specific details
Train train = trainFactory.TFactory("Express");
//Checks for error when making train
if (train == null)
MessageBox.Show("Can't Create Train");
else //Executes adding a new Express Train
{
//Stores the details of the textboxes/Combo boxes into the train details for each Train object
train.Type = cbxType.Text;
train.Departure = cbxDepartStation.Text;
train.Destination = cbxDepartStation.Text;
//Converts the time into DateTime format before passing to variable
train.DepartureTime = TimeSpan.Parse(txtDepartureTime.Text);
//Converts the date into DateTime format before passing to variable
train.DepartureDay = DateTime.Parse(txtDepartureDay.Text);
//If intermediate stops are selected. Throw exception
if (chbPeterborough.IsChecked == true || chbDarlington.IsChecked == true ||
chbYork.IsChecked == true || chbNewcastle.IsChecked == true)
{
throw new Exception();
}
//If first class radio button is checked, sets first class to true, else false
if (chbFirstClass.IsChecked == true)
{
train.FirstClass = true;
}
else
{
train.FirstClass = false;
}
//Adds a train object to the train list with its specific details
trains.add(train);
//String to hold all the Intermediate stops together in one for displaying to user
string intStops = string.Join(", ", train.IntermediateStop.Where(s => !string.IsNullOrEmpty(s)));
//Sql sequence to connect to database and insert details of each train
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Trains.mdf;Integrated Security=True");
SqlCommand cmd = new SqlCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "INSERT train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
"VALUES ( #trainID , #departure, #destination, #type, #intermediate, #dep_time, #dep_date, #sleep, #first)";
cmd.Parameters.AddWithValue("#trainID", train.TrainID);
cmd.Parameters.AddWithValue("#departure", train.Departure);
cmd.Parameters.AddWithValue("#destination", train.Destination);
cmd.Parameters.AddWithValue("#type", train.Type);
cmd.Parameters.AddWithValue("#intermediate", intStops);
cmd.Parameters.AddWithValue("#dep_time", train.DepartureTime);
cmd.Parameters.AddWithValue("#dep_date", train.DepartureDay);
cmd.Parameters.AddWithValue("#sleep", train.SleeperBerth);
cmd.Parameters.AddWithValue("#first", train.FirstClass);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
The whole AttachDbFileName= approach is flawed - at best! When running your app in Visual Studio, it will be copying around the .mdf file (from your App_Data directory to the output directory - typically .\bin\debug - where you app runs) and most likely, your INSERT works just fine - but you're just looking at the wrong .mdf file in the end!
If you want to stick with this approach, then try putting a breakpoint on the myConnection.Close() call - and then inspect the .mdf file with SQL Server Management Studio - I'm almost certain your data is there.
The real solution in my opinion would be to
install SQL Server Express (and you've already done that anyway)
install SQL Server Management Studio
create your database in SSMS, give it a logical name (e.g. Trains)
connect to it using its logical database name (given when you create it on the server) - and don't mess around with physical database files and user instances. In that case, your connection string would be something like:
Data Source=.\\SQLEXPRESS;Database=Trains;Integrated Security=True
and everything else is exactly the same as before...
Also see Aaron Bertrand's excellent blog post Bad habits to kick: using AttachDbFileName for more background info.
Try to change this code
cmd.CommandText = "INSERT train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
"VALUES ( #trainID , #departure, #destination, #type, #intermediate, #dep_time, #dep_date, #sleep, #first)";
into
cmd.CommandText = "INSERT INTO train (id, departure, destination, type, intermediate, departure_time, departure_date, sleeperBerth, firstClass) " +
"VALUES ( #trainID , #departure, #destination, #type, #intermediate, #dep_time, #dep_date, #sleep, #first)";
I only added INTO in your INSERT text query

creating a table on the fly, where did it go?

I'm making a table, if the name doesn't already exist
string sc1 = #"IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_NAME = #name) SELECT 1 ELSE SELECT 0";
string sc2 = #"CREATE TABLE dbo.Data" + pv.tablecounter + "(testdescription VARCHAR(25), testvalue VARCHAR(5))";
SqlCommand check1 = new SqlCommand(sc1, connection);
check1.Parameters.Add("#name", SqlDbType.VarChar).Value = "Data" + pv.tablecounter;
SqlCommand check2 = new SqlCommand(sc2, connection);
exists = Convert.ToInt32(chec.ExecuteScalar());
if(exists == 1)
{
MessageBox.Show("table exists, will not create new one");
}
else
{
MessageBox.Show("table wasn't found, creating now");
check2.ExecuteNonQuery();
}
i can verify that this is all "working" (the correct message will show, and it will find the newly created table and give me the right message). My connection string works fine
my question is, where did it go? i can't browse and find it in the server explorer. this is probably basic but i cannot find any info about it. I have tried specifying the database
#"CREATE TABLE testdb.dbo.Data" + pv.tablecounter + "(testdescription VARCHAR(25), testvalue VARCHAR(5))";
Wth an error that database testdb does not exist , even though it's in my server explorer and i have been writing to it elsewhere using the same connection string
using Visual Studio 2017
thanks

Switch case in SQL 2008 Server R2

I've been trying to create a search function on a webpage / form. It's a bit complicated since it has multiple search boxes.
It has to search the sql database and return the right row(s).
I was looking for a switch equivalent to execute a certain query if a value is null or not. typically if the user doesn't enter the student ID (primary key) then it will go the queries that doesn't include the ID parameter. Not sure if it's the right logic. My knowledge in sql is quite limited atm, sorry if it's a basic question but i didn't find a solution on google since apparently nobody ever needed to do this. I'm looking a stored procedure of course
Here's what I'm thinking of firing into a SQL
using (SqlCommand cmd = new SqlCommand("Student_CRUD"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Action", "SEARCH");
cmd.Parameters.AddWithValue("#StudentID", StudentID);
cmd.Parameters.AddWithValue("#FirstName", Name);
cmd.Parameters.AddWithValue("#Class", Class);
cmd.Parameters.AddWithValue("#RollNumber", RollNumber);
cmd.Connection = con;
con.Open();
try
{
cmd.ExecuteNonQuery();
con.Close();
}
catch (SqlException exp)
{
Response.Write(exp);
}
}
You can do this in the query inside the stored procedure:
WHERE FirstName = #FirstName
AND (#StudentID IS NULL OR (StudentID = #StudentID))
AND (#Class NULL OR (Class = #Class))
....
But, you have to set the #studentID value to null (DBNull.Value) in your code, so that the null value will be passed to the sql query. So when passing a null value to this query, the condition will be ignored.

MySqlCommand.ExecuteNonQuery() not filling MySqlParameter(s)

Background: I am rewriting my ASP.NET application - currently it uses MS SQL database but I need to support also MySQL (both in the same time!).
Most of work is done - I used MySQL Connector/Net for work with MySQL database from C# (Visual Studio 2010) - but I have troubles with certain SQL queries. This is SQL query I need to execute:
"SELECT #username=username FROM t_Users WHERE id=#id"
Here is my code:
public static int ExecuteSqlNonQuery(string i_szQuery)
{
bool bConnectionWasOpen = false;
AbstractConnection dbConnection = CMSSQLInstanceCreator.CreateConnection();
if(dbConnection.IsMySQL())
{
MySqlConnection aSqlConnection = dbConnection.GetMysConnection();
try
{
if (aSqlConnection.State == System.Data.ConnectionState.Closed)
aSqlConnection.Open();
else
if (aSqlConnection.State == System.Data.ConnectionState.Open)
bConnectionWasOpen = true;
else
throw new ApplicationException("Connection not available!");
List<MySqlParameter> aParameters1 = new List<MySqlParameter>();
aParameters1.Add(new MySqlParameter("#username", MySqlDbType.VarString, 128));
aParameters1.Add(new MySqlParameter("#id", MySqlDbType.Int32));
aParameters1[0].Direction = System.Data.ParameterDirection.Output;
aParameters1[1].Direction = System.Data.ParameterDirection.Input;
aParameters1[1].Value = (int)1;
MySqlCommand aSqlCommand = new MySqlCommand(i_szQuery, aSqlConnection);
aSqlCommand.CommandType = System.Data.CommandType.Text;
aSqlCommand.CommandTimeout = 0;
aSqlCommand.Parameters.Clear();
aSqlCommand.Parameters.AddRange(aParameters1.ToArray());
int iResult = aSqlCommand.ExecuteNonQuery();
if(iResult <= 0)
Debug.WriteLine("aResult <= 0: " + i_szQuery);
return iResult;
}
catch (Exception ex)
{
throw new ApplicationException("Cannot execute query!\nReason: '" + ex.Message + "'", ex);
}
finally
{
if (!bConnectionWasOpen && aSqlConnection.State == System.Data.ConnectionState.Open)
aSqlConnection.Close();
}
}
else
{
//... almost the same for MS SQL
}
}
The problem is that the Output parameter #username (System.Data.ParameterDirection.Output;) is not filled with the value from query.
If I use other query - e.g.
UPDATE t_Users SET password=#new_password WHERE (password=#old_password AND id=#user)
Everything is fine.
I cannot return scalar as there are many other queries like
SELECT #username=username, #is_blocked=is_blocked, #full_name=full_name, #must_change_pwd=must_change_pwd ...
returning many values and I do not want to rewrite most of code.
It looks like there is problem only in MySQL because the same code works with MS SQL fine.
What should I use to force MySqlParameter to load the value from query?
You should be able to read the value of the output like this
aSqlCommand.Parameters["#username"].Value
It apparently is a shortcoming in the MySql .Net connector, see #75267. Tested it with connector v6.9.7 and MySql server 5.5.45. It is still broken and the bug report - of december 2014 - is still open. Output parameters work for stored procedures, with a command type StoredProcedure, and do not work for a SELECT statement that assigns output parameters as part of the select; command type Text.
2023-02-16 Update. A couple of weeks ago it is fixed in version 8.0.32. I tested it by updating Connector/NET to 8.0.32, and by using NuGet package MySql.Data 8.0.32.
A command of type text, an output parameter and an ExecuteNonQuery now works for the following case:
SET #valNum:=(SELECT ValueNumber FROM `sky.application` WHERE Name='Agents')
Value #valNum can then be retrieved through the output parameter.
Note that retrieving two values does not work as follows, despite it does the job in the Workbench:
SELECT #valNum:=ValueNumber, #instNum:=InstanceNumber FROM `sky.application` WHERE Name='Agents'
Error: Parameter 'valNum:=ValueNumber' not found in the collection.
Same error if retrieving one value.
Fortunately the following syntax works:
SELECT ValueNumber, InstanceNumber INTO #valNum, #instNum FROM `sky.application` WHERE Name='Agents'

Iterating through a column in a database

When 'login' button is clicked I would like to iterate through a column in a table and check if a match occurs. How would I go about doing this?
I have connected through to a database and I'm reading from database and writing to database fine. I am not sure how I would iterate through a database.
P.S I'm new to both c# and visual studios. I am not having much trouble with C#, since I come over from Java however I'm struggling to get into grips with Visual studios.
This is simple you'll see.
SqlConnection myConnection = new SqlConnection(#"Server = (Local); Integrated Security = True;" + "Database = insertDataBaseName"); // Assuming (Local)
myConnection.Open();
SqlCommand myCommand = myConnection.CreateCommand();
myCommand.CommandText = ("SELECT UserName, Password,from Login"); // Where Login is your table . UserName and Password Columns
SqlDataReader myReader = myCommand.ExecuteReader();
bool login = false;
while (myReader.Read())
{
if (userNameBox.Text.CompareTo(myReader["UserName"].ToString()) == 0 && passwordBox.Text.CompareTo(myReader["Password"].ToString()) == 0) // A little messy but does the job to compare your infos assuming your using a textbox for username and password
{
login = true;
}
}
if (login)
{
//Your're in.
}
else
{
MessageBox.Show("Invalid UserName or Password", "Access Denied"); // Error message
}
myReader.Close();
myConnection.Close(); // Just close everything
Hope this helps.
Dont hesitate if you have any question on this code part.
in sql something like this will help
Select top(1) from Users where Id = #Id
or in linq
var user = (from u in users
where u.Id == id
select u).SingleOrDefault();
If you are chekcing for a username password validation, I think you should not get all user records and loop Iterate thru that. What if you get 100000 user registrations ? You really want to iterate 100000 times ? Really ?
You should probably query for the purticular record you are looking for
Some thing like this
SELECT TOP 1 UserID,FIRSTNAME,LASTNAME,HASHED_PASSWORD,SALT WHERE USERNAME='kristy'
Execute that query againinst your database and see whether you have any records exist, If you have one record present, now you can validate the password with the data you have.

Categories