Updating ms access database [duplicate] - database

I am trying to create an SQL statement using user-supplied data. I use code similar to this in C#:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES ('" + someVariable + "', '" + someTextBox.Text + "');";
var cmd = new SqlCommand(sql, myDbConnection);
cmd.ExecuteNonQuery();
and this in VB.NET:
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES ('" & someVariable & "', '" & someTextBox.Text & "');"
Dim cmd As New SqlCommand(sql, myDbConnection)
cmd.ExecuteNonQuery()
However,
this fails when the user input contains single quotes (e.g. O'Brien),
I cannot seem to get the format right when inserting DateTime values and
people keep telling me that I should not do this because of "SQL injection".
How do I do it "the right way"?

Use parameterized SQL.
Examples
(These examples are in C#, see below for the VB.NET version.)
Replace your string concatenations with #... placeholders and, afterwards, add the values to your SqlCommand. You can choose the name of the placeholders freely, just make sure that they start with the # sign. Your example would look like this:
var sql = "INSERT INTO myTable (myField1, myField2) " +
"VALUES (#someValue, #someOtherValue);";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text);
cmd.ExecuteNonQuery();
}
The same pattern is used for other kinds of SQL statements:
var sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;";
// see above, same as INSERT
or
var sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;";
using (var cmd = new SqlCommand(sql, myDbConnection))
{
cmd.Parameters.AddWithValue("#someValue", someVariable);
using (var reader = cmd.ExecuteReader())
{
...
}
// Alternatively: object result = cmd.ExecuteScalar();
// if you are only interested in one value of one row.
}
A word of caution: AddWithValue is a good starting point and works fine in most cases. However, the value you pass in needs to exactly match the data type of the corresponding database field. Otherwise, you might end up in a situation where the conversion prevents your query from using an index. Note that some SQL Server data types, such as char/varchar (without preceding "n") or date do not have a corresponding .NET data type. In those cases, Add with the correct data type should be used instead.
Why should I do that?
It's more secure: It stops SQL injection. (Bobby Tables won't delete your student records.)
It's easier: No need to fiddle around with single and double quotes or to look up the correct string representation of date literals.
It's more stable: O'Brien won't crash your application just because he insists on keeping his strange name.
Other database access libraries
If you use an OleDbCommand instead of an SqlCommand (e.g., if you are using an MS Access database), use ? instead of #... as the placeholder in the SQL. In that case, the first parameter of AddWithValue is irrelevant; instead, you need to add the parameters in the correct order. The same is true for OdbcCommand.
Entity Framework also supports parameterized queries.

VB.NET Example Code
This is the example code for the wiki answer in vb.net, assuming Option Strict On and Option Infer On.
INSERT
Dim sql = "INSERT INTO myTable (myField1, myField2) " &
"VALUES (#someValue, #someOtherValue);"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
cmd.Parameters.AddWithValue("#someOtherValue", someTextBox.Text)
cmd.ExecuteNonQuery()
End Using
UPDATE
Dim sql = "UPDATE myTable SET myField1 = #newValue WHERE myField2 = #someValue;"
' see above, same as INSERT
SELECT
Dim sql = "SELECT myField1, myField2 FROM myTable WHERE myField3 = #someValue;"
Using cmd As New SqlCommand(sql, myDbConnection)
cmd.Parameters.AddWithValue("#someValue", someVariable)
Using reader = cmd.ExecuteReader()
' ...
End Using
' Alternatively: Dim result = cmd.ExecuteScalar()
' if you are only interested in one value of one row.
End Using

Related

Is there a version of PostgreSQL returning in Access DB?

I have an access database for which I need to run a query that is available in postgres DBs, I was wondering if there is a possible that this can be accomplished:
Insert into Table (Col1,Col2...) values(Val1,Val2,...) returning * (ore even just an id defining that specific set of data that was just inserted)?
I'm using c# to communicate to the DB.Anything would help, thank you.
The code I basically use is the following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
namespace Testquery1
{
class Program
{
static void Main(string[] args)
{
string query = "INSERT INTO Table ( Val1, Val2, Val3 ) values(14,2,1)";
Test1 queryselect = new Test1();
queryselect.dataconnection(query);
}
}
class Test1
{
public OleDbConnection connection = new OleDbConnection();
string path = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileloc = #"DataBase.accdb";
string provider = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=";
public void dataconnection(string query)
{
connection.ConnectionString = provider + path + fileloc;
Console.WriteLine(connection.ConnectionString);
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = query;
command.ExecuteNonQuery();
connection.Close();
}
}
}
Unfortunately with .net you cannot do a append or make table query between two different connections.
However, you CAN in Access.
If you have a working PostgreSQL SQL query that returns records, then you can simple save that query in Access (as a pass-through query.
You can now use that query in Access and send it to a NEW local table in Access. (Access supports this concept, .net does not)
You can thus either append or “make table” of that data.
And more interesting is you can even append between different connections in Access. So you can append from a PostgreSQL table to say a MySQL, or Oracle or FoxPro table inside of access.
Again, you can’t do this in .net.
So, assume a working raw SQL (PostgreSQL format) query that works in PostgreSQL? Take that SAME working query and save it in Access as a pass-through query.
Then in Access you can append to a table in Access (assuming same table structure with:
VBA (Access code)
Dim strSQL as string
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL
And if you want to MAKE a new table in Access with the SAME structure, so make table (not append), you can go:
Dim strSQL as string
strSQL = " SELECT * INTO LocalTable FROM qryPassR"
Currentdb.Execute strSQL
You can also in VBA code change the PostgreSQL to include criteria for that select.
(air code - does not take into account SQL injection issue).
Dim strCity as string.
strCity = inputbox("What city to pull from PostGres?")
dim strSQL as string
strSQL = "select * from tbleHotels where City = '" = strCity & "'"
With currentdb.QueryDefs("QryPassR"
.SQL = strSQL
End with
strSQL = "INSERT INTO LocalTable SELECT * from QryPassR"
Currentdb.Execute strSQL
‘ above will copy all the records from PostGreSQL of city = Edmonton into the Access table (called local table in this example).
And as noted, you not limited to “LocalTable” being a access table, it could be a FoxPro table, MySQL, SQL server etc. So you not limited to JUST using Access tables in the above with your given SQL. So any linked table you have in Access can be used – including ones that point to other database systems.
If you must use .net, then you have to:
Connect to first database.
Execute query to pull and fill a datatable.
Connect to second database.
Create (open) a data table based on second database.
Loop (iterate) each row from first connection datatable and copy the row into the second datatable (based on 2nd connection).
You have to do a row by row copy. (but there is ImportRow method of the .net datatable, so you don’t have to loop by a column by column copy.
(but you have to loop row by row).
In Access this looping is not required and in fact you can use SQL commands that operate on both tables, including as per above the make table and append, and you can even do relation joins between such tables - even those based on different connections (data sources).
Edit
Based on comments, it looks like the simple question is:
After I insert a row into Access, how can I get the last ID (identity) of that insert?
The follow vb.net code will do this:
Imports System.Data.OleDb
Dim MyCon As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test2\test44.accdb")
MyCon.Open()
Dim strSQL As String = "insert into tblHotels2 (City) VAlues('Edmonton')"
Dim cmd As New OleDb.OleDbCommand(strSQL, MyCon)
Dim r As Integer
cmd.ExecuteNonQuery()
cmd.CommandText = "select ##IDENTITY"
r = cmd.ExecuteScalar
Debug.Print(r)
Output = last PK id (autonumber)

The SQL statement works properly in SQL Server database, but errors in vb.net

I need to insert new record into a SQL Server database, but get
Incorrect syntax error
The strange thing is when I try to query the same statement in SQL Server itself, it works properly.
The code in vb.net is as follows:
insertSql = "INSERT INTO Seg_LINE VALUES (" & OBJECTID & ", 'test" + "', '" + "test" + "','" + DrainName + "'," & UID & ")"
logger.Info("insert sql = " + insertSql)
Dim cmdInsert As New SqlClient.SqlCommand(insertSql, Sqlconnection)
cmdInsert.ExecuteNonQuery()
The OBJECTID and UID are number parameters.
I cannot figure out what's wrong with my code, I am using vb.net(vs2102).
Most likely you have a DrainName value with a single quote in it. You're lucky the query is just failing, and not executing unwanted commands on your DB server. Don't use string concatenation like that to build queries! You need to use query parameters, like this:
insertSql = "INSERT INTO Seg_LINE VALUES (#ObjectID, 'test', 'test', #DrainName, #UID)"
logger.Info("insert sql = " + insertSql)
Dim cmdInsert As New SqlClient.SqlCommand(insertSql, Sqlconnection)
'I'm guessing at these parameter types. Use the actual db types of the columns
cmdInsert.Parameters.Add("#ObjectID", SqlDbType.Int).Value = OBJECTID
cmdInsert.Parameters.Add("#DrainName", SqlDbType.NChar, 50).Value = DrainName
cmdInsert.Parameters.Add("#UID", SqlDbType.Int).Value = UID
cmdInsert.ExecuteNonQuery()
Changing the code this way will also likely fix your syntax error.

Sql select statement with two conditions in visual basic

I am trying to retrieve Two Columns; App_ID & App_Slot from a table su_Appointments from an sql server database using vb, and I have two conditions the Date and Time; App_Date & App_Time for the query, now when I run the query it throws an error saying : Incorrect syntax near '2014'. The query is as follows
I am going to store App_ID into the variable AP_ID
CODE
Using Query As New SqlCommand("Select App_ID From su_Appointments Where (App_Date = ' and App_Time = ' )" & DT & TM, sqlcon)
sqlcon.Open()
Dim dr As SqlDataReader = Query.ExecuteReader()
While dr.Read()
AP_ID = dr(0)
End While
End Using
sqlcon.Close()
Well, your syntax is effectively wrong
A SELECT statement requires
SELECT <fieldA>, <FieldB>, ....
FROM <Table>
WHERE <FieldX> = <Condition1> AND <FieldZ> = <Condition2>
But, a part from this basic error, you need to start using a parameterized query approach
Using sqlcon = new SqlConnection(.....connectionstring...)
Dim cmdText = "Select App_ID From su_Appointments Where App_Date =#dt and App_Time = #tm"
Using Query = New SqlCommand(cmdText, sqlcon)
sqlcon.Open()
Query.Parameters.AddWithValue("#dt", DT)
Query.Parameters.AddWithValue("#tm", TM)
Using dr =Query.ExecuteReader()
While dr.Read()
AP_ID = dr(0)
End While
End Using
End Using
End Using
With a parameterized query, you get many benefits. There is no possibility of Sql Injection Attacks, the text of your command is more clear and understandable, the parameters are treated for correct quoting by the code itself so you don't need to check for single quotes inside your strings, or format correctly dates and decimal numbers.
Eventually, you could encounter a different problem. If your columns App_Date and App_Time are of type datetime then you need to pass parameters of the appropriate type, not simply strings. Instead if, these fields are of type nvarchar (or some other kind of text type) then you pass strings but you will have problems storing and querying correctly in these fields.

how to insert update and delete records in tables

I have a large windows form with 50 different fields (text boxes,combo boxes,listview,check box) i have 10 tables in sql server database each table have different column I want to insert my windows forms 50 fields in these 10 tables. Here is my code to insert record in a table
Dim cmd As New SqlCommand
cmd.Connection = conn
cmd.CommandText = "Insert Into ChartOfAccount (MainCode,MainDescription,AccountCode,AccountDescription,OpeningBalance) values ('" & MainCode & "','" & MainDescription & "','" & AccountCode & "','" & AccountDescription & "','" & OpeningBalance & "')"
cmd.ExecuteNonQuery()
So question is if I insert data into 10 different tables then I need to write 10 insert statments.
If I update or delete record I need to write update and delete command 10 tables seprately
this will take long time please guide me if any short method exists.
Your query is susceptible with SQL injection so better to use parameters:
Dim connStr as String = "connection string values here";
using con as new SqlConnection(connStr)
Dim commandText as String =
#"Insert Into ChartOfAccount (MainCode
,MainDescription,AccountCode
,AccountDescription,OpeningBalance)
VALUES
(#MainCode, #MainDesc,#AccountCode
,#AccountDesc,#OpeningBalance)"
Dim cmd as New SqlCommand(commandText,con)
cmd.Parameters.AddWithValue("#MainCode",MainCode)
cmd.Parameters.AddWithValue("#MainDesc",MainDescription)
cmd.Parameters.AddWithValue("#AccountCode",AccountCode)
cmd.Parameters.AddWithValue("#AccountDesc",AccountDescription)
cmd.Parameters.AddWithValue("#OpeningBalance",OpeningBalance)
Try
con.Open()
cmd.ExecuteNonQuery()
Catch ex as Exception
MessageBox.Show(ex.Message)
End Try
End Using
Now, this is only for Inserting records example.
You can create a stored procedure for that. In order to create a stored procedure, you can use the following SQL query:
Create procedure [dbo].[NewUser]
#Yourparameter1 int ,
#Yourparamtere2
As
Insert into dbo.Users
(
// Db columns
Column1 ,
Column2
)
values
(
#Yourparameter1
#Yourparameter2
)
And in your C# code, create a SQLParameter collection and pass it to the procedure. It will work fine and smoothly, and this way your code will be simpler.

connection.execute

`Dim con1 As New ADODB.Connection
Dim rs1 As New ADODB.Recordset
Dim sql1 As String
sql1 = "Update Balance set Balance_Amt = (Balance_Amt + " & a & ") where Company = " & Combo3.Text
con1.Execute (sql1)
"Can anyone say why this code does not work? It says No value for one or more required parameters"
I would guess that the immediate problem is that the SQL fragment
where Company = value
is invalid SQL. It should be quoted:
where Company = 'value'
But you really should be using SQL parameters.
I would have avoided this issue since the parameter would have been automatically quoted as necessary.
It would have made the code easier to read.
It would not be susceptible to SQL Injection attacks.
e.g.
Using cmd = new SqlCommand("UPDATE Balance SET Balance_Amt = (Balance_Amt + #a) WHERE Company=#company", con1)
cmd.Parameters.AddWithValue("#a", a)
cmd.Parameters.AddWithValue("#company", company)
cmd.ExecuteNonQuery()
End Using
Print out the sql statement and see if it is ok, copy/paste it to the sql management studio.
I think you are missing apostrophes around the string Combo3.Text.
Also consider what sql it would result in if Combo3.Text contains
'a'; delete from Balance

Resources