I am new to SQL . As shown in the screenshot (SQL table) I want to get the circled cell value (3.4000) from this table and save it in a variable in C#. I just need the query and how to save it in a variable. Thank you in advance.
DECLARE #var float;
SET #var=(select Price2 from table where pizzaType='Hawaiian')
A bit generalized case. Providing that the RDBMS is MS SQL (if it's not your case, use appropriate Connection and Command classes instead of SqlConnection and SqlCommand ones) and you want Decimal value as a result
using (SqlConnection con = new SqlConnection(YourConnectionString)) {
con.Open();
using (SqlCommand q = con.CreateCommand()) {
q.CommandText = String.Format(
#"select {0}
from MyTable -- put actual table name here
where PizzaType = #prmPizzaType", "Price2");
q.Parameters.AddWithValue("#prmPizzaType", "Hawaiian");
using (var reader = q.ExecuteReader()) {
if (reader.Read()) {
// you may want to check if value is NULL: reader.IsDBNull(0)
Decimal value = Convert.ToDecimal(reader[0]);
if (reader.Read()) {
//TODO: At least 2 values: put your code here
}
}
else {
//TODO: no such value: put your code here
}
}
}
}
The query for this would be something along the lines of
select Price2 from <tablename> where PizzaType = "Hawaiian"
As far as storing the value, I believe this question will help with that: Reading values from SQL database in C#
I think it's not possible anymore like that. You need to store your query result in a DataGridView table, then take whatever you want from the DataGridView easily.
Related
I have a stored procedure that returns 0 or 1 depending on certain outcomes. I often execute this procedure manually, so to have a description of the success/failure that's easily viewed in SSMS but still readable as 0/1 in code, I select the 0 or 1 as a different column name, i.e. SELECT 0 AS ThisReason or SELECT 0 AS ThatReason.
There is almost certainly a better way to handle this, but it got me curious - is it possible to read the name of the column you've selected when using ExecuteScalar in C#?
Not with ExecuteScalar but with ExecuteReader and SqlDataReader.GetName:
using (var con = new SqlConnection("connection-string"))
using (var cmd = new SqlCommand("storedprocedurename", con))
{
cmd.CommandType = CommandType.StoredProcedure;
// parameters here...
con.Open();
using (var rd = cmd.ExecuteReader())
{
if (rd.Read())
{
string column = rd.GetName(0); // first column
int value = rd.GetInt16(0); // or rd.GetInt32(0)
}
}
}
What you want to do is to get two bits of information as a result of a query. To use ExecuteScalar you will need to first "pack" those two bits into one. For example you could return a string starting with "+" or "-" indicating the success/failure, and the rest of the string could be a "reason".
There is no other way to do this with ExecuteScalar.
I am making something that requires MySQL. I have the saving done from in-game, which is simply done by INSERT.
I have a column that will have a password in and I need to check if the inputted password matched any of the rows and then if it is, get all of the contents of the row then save it to variables.
Does anyone have an idea how to do this in C#?
//////////////////////////
I have found how to save and get the string, however it will only get 1 string at a time :(
MySql.Data.MySqlClient.MySqlCommand command = conn.CreateCommand();
command.CommandText = "SELECT * FROM (player) WHERE (pass)";
command.ExecuteNonQuery();
command.CommandType = System.Data.CommandType.Text;
MySql.Data.MySqlClient.MySqlDataReader reader = command.ExecuteReader();
reader.Read();
ayy = reader.GetString(1);
print (ayy);
if(ayy == password){
//something
}
My best practice is to use MySQLDataAdapter to fill a DataTable. You can then iterate through the rows and try to match the password.
Something like this;
DataTable dt = new DataTable();
using(MySQLDataAdapter adapter = new MySQLDataAdaper(query, connection))
{
adapter.Fill(dt);
}
foreach(DataRow row in dt.Rows)
{
//Supposing you stored your password in a stringfield in your database
if((row.Field<String>("columnName").Equals("password"))
{
//Do something with it
}
}
I hope this compiles since I typed this from my phone. You can find a nice explanation and example here.
However, if you are needing data from a specific user, why not specificly ask it from the database? Your query would be like;
SELECT * FROM usercolumn WHERE user_id = input_id AND pass = input_pass
Since I suppose every user is unique, you will now get the data from the specific user, meaning you should not have to check for passwords anymore.
For the SQL statement, you should be able to search your database as follows and get only the entry you need back from it.
"SELECT * FROM table_name WHERE column_name LIKE input_string"
If input_string contains any of the special characters for SQL string comparison (% and _, I believe) you'll just have to escape them which can be done quite simply with regex. As I said in the comments, it's been a while since I've done SQL, but there's plenty of resources online for perfecting that query.
This should then return the entire row, and if I'm thinking correctly you should be able to then put the entire row into an array of objects all at once, or simply read them string by string and convert to values as needed using one of the Convert methods, as found here: http://msdn.microsoft.com/en-us/library/system.convert(v=vs.110).aspx
Edit as per Prix's comment: Data entered into the MySQL table should not need conversion.
Example to get an integer:
string x = [...];
[...]
var y = Convert.ToInt32(x);
If you're able to get them into object arrays, that works as well.
object[] obj = [...];
[...]
var x0 = Convert.To[...](obj[0]);
var x1 = Convert.To[...](obj[1]);
Etcetera.
I have a very big string to be updated to the memo field of FoxPro Table, I tried
cmd = db.GetSqlStringCommandWrapper("UPDATE xxx SET memo1 = "adfsd" WHERE condition1 = 'satisfied'");
db.ExecuteNonQuery(cmd);
This query overwrites the previous values in the memo1.
I Cannot use MODIFY memo in C#.
How do I append a string to a already existing memo field in Foxpro using C# ?
Try making the command say:
UPDATE xxx SET memo1 = memo1 + "adfsd"
I think the issue is probably with GetSqlStringCommandWrapper which as far as I can see is deprecated.
This shouldn't be a problem to do, for example using the OLEDB provider:
var DBC = #"C:\mydata.dbc";
string ConnectionString = string.Format("Provider=VFPOLEDB.1;Data Source={0};Exclusive=false;Ansi=true;OLE DB Services = 0", DBC);
using (OleDbConnection testConnection = new OleDbConnection(ConnectionString))
{
OleDbCommand updateCommand = new OleDbCommand(#"update mytable set mymemo=alltrim(mymemo)+ttoc(datetime()) where thisfield='THISVALUE'", testConnection);
testConnection.Open();
updateCommand.ExecuteNonQuery();
Console.WriteLine(#"Finished - press ENTER.");
Console.ReadLine();
}
You need to parameterize your query.. Assuming your query wrapper gets the sql connection handle to the database. The VFP OleDB Provider uses "?" as a "place-holder" for parameters and must match the order as associated to your query.
I have a more detailed sample to a very similar question here...
Try something like
string whatToSetItTo = "this is a test string that can even include 'quotes'";
cmd = db.GetSqlStringCommandWrapper("UPDATE YourTable SET memo1 = ? WHERE someKeyColumn = ?");
cmd.Parameters.Add( "parmForMemoField", whatToSetItTo);
cmd.Parameters.Add( "parmForKeyColumn", "satisfied" );
db.ExecuteNonQuery(cmd);
Notice the parameters added in same sequence. whatever the string value is (or could even be integer, date, etc respective to your table structure, but your sample only was based on strings) the place-holders are filled in order. The values would update accordingly.
i would like to know what is the standard/best way of doing the following:
i have a form web app in asp.net and using C#
the user will enter data into the form and click INSERT and it will insert data into 4 different tables.
the fields are:
primarykey, animal, street, country
the form allows for multiple animals, multiple streets and multiple countries per primarykey. so when i have data like this:
[1],[rhino,cat,dog],[luigi st, paul st], [russia,israel]
i need it inserted into tables like this:
table1:
1,rhino
1,cat
1,dog
table2:
1,luigi st
1, paul st
table3:
1,russia
1,israel
questions
I'm at a total loss on how to do this. if i just had one table and one set of data per primary key i would just use the InsertQuery and do it this way, but since it is multiple tables i don't know how to do this??
what control(s) should i use in order to allow user to input multiple values? currently i am just using textboxes and thinking of separating the entries by semi colons, but that's probably not the right way.
I wanted to recommend that you take advantage of the new multirow insert statement in SQL 2008 so that you can just pass a sql statement like this:
INSERT INTO table1(id,animal_name) values (1,cat),(1,dog),(1,horse)...
To your SqlCommand but I don't know how to build a statement like that w/o risking being victim of a SQL Injection Attack.
Another alternative is to define data table types in your sql database:
And then construct a DataTable in C# that matches your datatable type definition:
DataTable t = new DataTable();
t.Columns.Add("id");
t.Columns.Add("animal_name");
foreach(var element in your animals_list)
{
DaraRow r = t.NewRow();
r.ItemArray = new object[] { element.id, element.animal_name };
t.Rows.Add(r);
}
// Assumes connection is an open SqlConnection.
using (connection)
{
// Define the INSERT-SELECT statement.
string sqlInsert = "INSERT INTO dbo.table1 (id, animal_name) SELECT nc.id, nc.animal_name FROM #animals AS nc;"
// Configure the command and parameter.
SqlCommand insertCommand = new SqlCommand(sqlInsert, connection);
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue("#animals", t);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.AnimalTable";
// Execute the command.
insertCommand.ExecuteNonQuery();
}
Read more here.
Or if you are familiar with Stored Procedures, same as previous suggestion but having the stored procedure receive the DataTable t as parameter.
If none of the above work for you, create a SqlTranscation from the Connection object and iterate through each row of each data set inserting the record in the appropriate table and finally commit the transaction. Example here.
Use Checkboxes on the front end. Have a service/repository to save the user data. Something like the following:
public void UpdateUserAnimals(Guid userId, string[] animals)
{
using (SqlConnection conn = new SqlConnection("connectionstring..."))
{
using (SqlCommand cmd = new SqlCommand("Insert Into UserAnimals(UserId, Animals) values (#UserId, #Animal)"))
{
conn.Open();
cmd.Parameters.AddWithValue("#UserId", userId);
foreach(string animal in animals)
{
cmd.Parameters.AddWithValue("#Animal", animal);
cmd.ExecuteNonQuery();
}
}
}
}
There are more complex solutions, but this is a simple one.
I have a simple problem with a not so simple solution... I am currently inserting some data into a database like this:
kompenzacijeDataSet.KompenzacijeRow kompenzacija = kompenzacijeDataSet.Kompenzacije.NewKompenzacijeRow();
kompenzacija.Datum = DateTime.Now;
kompenzacija.PodjetjeID = stranka.id;
kompenzacija.Znesek = Decimal.Parse(tbZnesek.Text);
kompenzacijeDataSet.Kompenzacije.Rows.Add(kompenzacija);
kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter kompTA = new kompenzacijeDataSetTableAdapters.KompenzacijeTableAdapter();
kompTA.Update(this.kompenzacijeDataSet.Kompenzacije);
this.currentKompenzacijaID = LastInsertID(kompTA.Connection);
The last line is important. Why do I supply a connection? Well there is a SQLite function called last_insert_rowid() that you can call and get the last insert ID. Problem is it is bound to a connection and .NET seems to be reopening and closing connections for every dataset operation. I thought getting the connection from a table adapter would change things. But it doesn't.
Would anyone know how to solve this? Maybe where to get a constant connection from? Or maybe something more elegant?
Thank you.
EDIT:
This is also a problem with transactions, I would need the same connection if I would want to use transactions, so that is also a problem...
Using C# (.net 4.0) with SQLite, the SQLiteConnection class has a property LastInsertRowId that equals the Primary Integer Key of the most recently inserted (or updated) element.
The rowID is returned if the table doesn't have a primary integer key (in this case the rowID is column is automatically created).
See https://www.sqlite.org/c3ref/last_insert_rowid.html for more.
As for wrapping multiple commands in a single transaction, any commands entered after the transaction begins and before it is committed are part of one transaction.
long rowID;
using (SQLiteConnection con = new SQLiteConnection([datasource])
{
SQLiteTransaction transaction = null;
transaction = con.BeginTransaction();
... [execute insert statement]
rowID = con.LastInsertRowId;
transaction.Commit()
}
select last_insert_rowid();
And you will need to execute it as a scalar query.
string sql = #"select last_insert_rowid()";
long lastId = (long)command.ExecuteScalar(sql); // Need to type-cast since `ExecuteScalar` returns an object.
last_insert_rowid() is part of the solution. It returns a row number, not the actual ID.
cmd = CNN.CreateCommand();
cmd.CommandText = "SELECT last_insert_rowid()";
object i = cmd.ExecuteScalar();
cmd.CommandText = "SELECT " + ID_Name + " FROM " + TableName + " WHERE rowid=" + i.ToString();
i = cmd.ExecuteScalar();
I'm using Microsoft.Data.Sqlite package and I do not see a LastInsertRowId property. But you don't have to create a second trip to database to get the last id. Instead, combine both sql statements into a single string.
string sql = #"
insert into MyTable values (null, #name);
select last_insert_rowid();";
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = sql;
cmd.Parameters.Add("#name", SqliteType.Text).Value = "John";
int lastId = Convert.ToInt32(cmd.ExecuteScalar());
}
There seems to be answers to both Microsoft's reference and SQLite's reference and that is the reason some people are getting LastInsertRowId property to work and others aren't.
Personally I don't use an PK as it's just an alias for the rowid column. Using the rowid is around twice as fast as one that you create. If I have a TEXT column for a PK I still use rowid and just make the text column unique. (for SQLite 3 only. You need your own for v1 & v2 as vacuum will alter rowid numbers)
That said, the way to get the information from a record in the last insert is the code below. Since the function does a left join to itself I LIMIT it to 1 just for speed, even if you don't there will only be 1 record from the main SELECT statement.
SELECT my_primary_key_column FROM my_table
WHERE rowid in (SELECT last_insert_rowid() LIMIT 1);
The SQLiteConnection object has a property for that, so there is not need for additional query.
After INSERT you just my use LastInsertRowId property of your SQLiteConnection object that was used for INSERT command.
Type of LastInsertRowId property is Int64.
Off course, as you already now, for auto increment to work the primary key on table must be set to be AUTOINCREMENT field, which is another topic.
database = new SQLiteConnection(databasePath);
public int GetLastInsertId()
{
return (int)SQLite3.LastInsertRowid(database.Handle);
}
# How about just running 2x SQL statements together using Execute Scalar?
# Person is a object that has an Id and Name property
var connString = LoadConnectionString(); // get connection string
using (var conn = new SQLiteConnection(connString)) // connect to sqlite
{
// insert new record and get Id of inserted record
var sql = #"INSERT INTO People (Name) VALUES (#Name);
SELECT Id FROM People
ORDER BY Id DESC";
var lastId = conn.ExecuteScalar(sql, person);
}
In EF Core 5 you can get ID in the object itself without using any "last inserted".
For example:
var r = new SomeData() { Name = "New Row", ...};
dbContext.Add(r);
dbContext.SaveChanges();
Console.WriteLine(r.ID);
you would get new ID without thinking of using correct connection or thread-safety etc.
If you're using the Microsoft.Data.Sqlite package, it doesn't include a LastInsertRowId property in the SqliteConnection class, but you can still call the last_insert_rowid function by using the underlying SQLitePCL library. Here's an extension method:
using Microsoft.Data.Sqlite;
using SQLitePCL;
public static long GetLastInsertRowId(this SqliteConnection connection)
{
var handle = connection.Handle ?? throw new NullReferenceException("The connection is not open.");
return raw.sqlite3_last_insert_rowid(handle);
}