How to check if mysql table is empty? - c#

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

Related

Need to select a value from table and store it into variable

Hello everyone I am currently working on some testing project and I am having a little problem. Using selenium, I need to SendKey in specific element but instead of fixed value i need to use value (data) from my database. Can anyone help me with how to retrieve single value from database and store it in a variable so i can use it later.
Thank you and sorry for a noobish question - see code below:
SqlConnection conn = new SqlConnection();
SqlCommand command;
SqlDataReader dataReader;
conn.ConnectionString = "Server=******;Database=****;User ID=sqlserver;password=****;MultipleActiveResultSets=true;");
string query = "select RequestID, from AutomaticPayment where RequestID ='1230322'";
DataTable dt = new DataTable();
command = new SqlCommand(query, conn);
conn.Open();
dataReader = command.ExecuteReader();
dt.Load(dataReader);
driver.FindElement(By.Id("requestID")).SendKeys(VALUE FROM DATABASE);
You can use the following code
using (SqlConnection connection = new SqlConnection(_connectionString))
{
SqlDataAdapter sda = new SqlDataAdapter(query, connection);
connection.Open();
SqlCommand cmd = new SqlCommand(query, connection);
try
{
result = cmd.ExecuteScalar().ToString();
}
catch(NullReferenceException n)
{
result = "";
}
}
ExecuteScaler gets you the first column of the first row and additional columns are ignored. Use the value from result in your SendKeys()
Use conditions to limit the result:
Select data
SELECT TOP 1 RequestID FROM AutomaticPayment // Always returns 1 row
Or
SELECT RequestID FROM AutomaticPayment WHERE Id = 123 // Id must be unique to return 1 row
And maybe other ways.
Get value
var value = dt.Rows[0][1];
Or
var value = dt.Rows[0]["RequestID"];
From what i worked on with SqlCommand just do the following :
int yourId = 0;
dataReader = command.ExecuteReader()
while(dataReader.Read())
{
yourId = dataReader.GetInt32(0);
}
With that, you should have your value set to the first column of the dataReader. (that is selected thanks to your query, since you are requesting on a specific id, i guess it will return only one column
there is many other type available for Reader : Reader Microsoft Doc
And if you have in the futur many data to collect, use the ORM entity framework, work well for me
Source
EDIT :
Since you are only querying one data, maybe the solution of #work_ishaan is better than mine in this case, check it out.

How to fix a Select Statement returning -1

I'm trying to return the InvoiceID from the database but it keeps returning -1.
I'm trying to select the invoice ID From tblInvoice to display it on a form and also use it to insert it into a second table that has a one to many relationship with tblInvoice.
try
{
conn = new SqlConnection(conString);
conn.Open();
string select = "SELECT TOP 1 FId FROM tblFaktuur ORDER BY FId DESC";
SqlCommand cmd1 = new SqlCommand(select, conn);
i = (int)cmd1.ExecuteNonQuery();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show("ReadInvoiceNumber()" + e.Message);
}
return i;
When Running the query SELECT TOP 1 FId FROM tblFaktuur ORDER BY FId DESC in SQL Server it returns the value of 6 which is the last Invoice ID.
Think about that code. How do you expect a method called ExecuteNonQuery to handle a Query? Change that to ExecuteScalar. This work Perfectly Thanks to #Camilo Terevinto, i will be doing research to improve my skills atleast i know what is wrong.

Getting an IndexOutOfRangeException when putting sql into an object array

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

Issues with Increment MS-SQL, C#

I am having an issue with the increment for the ID. The ID would increase by one every time I click insert, but the problem occurs when the ID 2, it would insert the values twice, if ID 3, it would insert the values three times, and so on.
There are couple of options that I have been trying. One is Max and the other one is finding the last inserted value and add one to the ID just.
I would appreciate if anyone can help me out with this. Thanks
public partial class LoginInfo : System.Web.UI.Page
{
static string myConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
private void GenerateID()
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery1 = "Select Count(S_ID) from Student_Name";
SqlCommand cmd = new SqlCommand(myQuery1, myConnection);
myConnection.Open();
int addOneS_ID_Table1 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneS_ID_Table1++;
lblstdID.Text = addOneS_ID_Table1.ToString();
myConnection.Open();
cmd.CommandText = "Select Count(P_ID) from Student_Pass";
int addOneP_ID_Table2 = Convert.ToInt32(cmd.ExecuteScalar());
myConnection.Close();
addOneP_ID_Table2++;
lblstdPass.Text = addOneP_ID_Table2.ToString();
/*-----------------------------------------------------------------*/
//SqlConnection myConnection = new SqlConnection(myConnectionString);
//SqlCommand cmd = new SqlCommand("SELECT MAX(S_ID) as max_S_ID from Student_Name",myConnection);
//cmd.CommandType = CommandType.Text;
//myConnection.Open();
//lblstdID.Text = Convert.ToString(cmd.ExecuteScalar());
//cmd.CommandText = "SELECT MAX(P_ID) as max_P_ID FROM Student_Pass";
//lblstdPass.Text = Convert.ToString(cmd.ExecuteScalar());
//myConnection.Close();
}
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
GenerateID();
}
}
protected void btnInsert_Click(object sender, EventArgs e)
{
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myQuery = "Insert into Student_Name(S_ID,STUDENT_NAME) VALUES" + "(#S_ID,#STUDENT_NAME)";
SqlCommand cmd = new SqlCommand(myQuery,myConnection);
cmd.Parameters.Add("#S_ID", SqlDbType.Int).Value = lblstdID.Text;
cmd.Parameters.Add("#STUDENT_NAME", SqlDbType.VarChar).Value = txtstdName.Text;
if(myConnection.State == ConnectionState.Closed)
{
myConnection.Open();
}
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
//Second Table
cmd.CommandText = "Insert into Student_Pass(P_ID,PASSWORD) VALUES" + "(#P_ID,#PASSWORD)";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#P_ID", SqlDbType.Int).Value = lblstdPass.Text;
cmd.Parameters.Add("#PASSWORD", SqlDbType.VarChar).Value = txtStdPass.Text;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
myConnection.Close();
GenerateID();
lblResult.Text = "Successfully Saved";
GridView1.DataBind();
}
}
Problem is with your query since you are getting COUNT(S_ID) which is going to get you count of records doesn't necessarily will give exact ID number. You should rather try MAX(S_ID) or ORDER BY clause saying
Select MAX(S_ID) from Student_Name
(OR)
Select TOP 1 S_ID from Student_Name ORDER BY S_ID DESC;
But recommended, You should actually go with SQL Server ##IDENTITY or SCOPE_IDENTITY() to get the last inserted record ID (assuming that S_ID is an IDENTITY column)
It's highly recommended to not use max or top in order to determine the "next" identifier to use, simply because of the cost associated with it.
However, there are some other pitfalls to using max and top especially if there is a chance that nolock is used (which is a whole other conversation). I've seen a lot of web applications use max and has proven to be a performance killer.
Rahul is right, ##identity or scope_identity are good alternatives. However, I think this calls for using a native SQL Server sequence, which was introduced in SQL Server 2012. It was something that application developers have been waiting for and Microsoft finally delivered.
The issue with using ##identity or scope_identity is that you actually have to write rows to some table before you can even contemplate doing something.
This makes it a bit more costly and messier than what it may need to be. In the case of using a sequence, you can issue a new sequence number and then decide what to do and once you decide what to do you're still guaranteed that you're the only one with that sequence number.
You would create a sequence like this. You should check out the documentation as well.
create sequence dbo.StudentIdSeq
as int -- this can be any integer type
start with 1 -- you can start with any valid number in the int, even negative
increment by 1;
go
Then you issue new sequence numbers by doing this ...
select next value for StudentIdSeq;
It may still be good to create a stored procedure with an output parameter that you can call from C# (which is what I would do). In fact you may want to take it a step further, in the case that you have a bunch of sequences, and create a slick stored procedure that will get a new sequence based on the type that is being requested from the caller.

SQL connection commands doesn't change the data

How can I know whether the table in database is affected after these instructions? I try to show the query result in console but it doesn't show anything.
static void Main(string[] args)
{
DateTime date = new DateTime(2013, 3, 4);
try
{
SqlConnection connection = new SqlConnection("Data Source=ExchangeRatesByDate/TestApplication/Rates_DB.sdf");
Console.WriteLine("Connection is created");
connection.Open();
Console.WriteLine("Connection is opened");
SqlCommand insertCommand = connection.CreateCommand();
insertCommand.CommandText = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)";
insertCommand.ExecuteNonQuery();
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Rates_Table", connection);
DataTable data = new DataTable();
adapter.Fill(data);
Console.WriteLine(adapter);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
ExecuteNonQuery() returns an integer showing number of affected rows. ExecuteNonQuery
You can use the ExecuteNonQuery to perform catalog operations (for
example, querying the structure of a database or creating database
objects such as tables), or to change the data in a database without
using a DataSet by executing UPDATE, INSERT, or DELETE statements.
Although the ExecuteNonQuery returns no rows, any output parameters or
return values mapped to parameters are populated with data.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
try like this
int updatedRows = insertCommand.ExecuteNonQuery();
if(updatedRows>0)
{
//do something
}
i think u are showing SqlDataAdapter object show to datatable ,and also use parameter for the insert string like 'USD'
the ExecuteNonQuery() returns an integer for the number of affected records.
int _affected = insertCommand.ExecuteNonQuery();
ExecuteNonQuery()
follow-up question
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (USD, 1, 417.5, date)
in the statement above, are values USD and date are real values because if so, it pretty sure it will thrown an exception. It should be wrap with single quotes like this:
INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES ('USD', 1, 417.5, '')
because they are string literals. But it's not the proper way to insert data with real values in the INSERT statement. The values should be parameterized to avoid sql injection.
string sqlStatement = "INSERT INTO Rates_Table(ISO, Amount, Rate, Date) VALUES (#iso, #Amount, #rate, #date)";
using (SqlConnection conn = new SqlConnection(connStr))
{
using(SqlCommand comm = new SqlCommand())
{
comm.Connection = conn;
comm.CommandText = sqlStatement;
comm.CommandType = CommandType.Text;
comm.Parameters.AddWithValue("#iso", '-- value --');
comm.Parameters.AddWithValue("#Amount", '-- value --');
comm.Parameters.AddWithValue("#rate", '-- value --');
comm.Parameters.AddWithValue("#date", '-- value --');
try
{
conn.Open();
int _affected = comm.ExecuteNonQuery();
}
catch(SqlException e)
{
// do something with the exception
// do not hide it
// e.Message.ToString()
}
}
}
For proper coding
use using statement for propr object disposal
use try-catch block to properly handle objects

Categories

Resources