I'm trying to make a program that copies data from one table to the other in other server.
The thing is table is not exactly same. So Let's say these are my tables:
Server A:
TableA (Col1, Col2, Col3)
Server B:
TableB (Col1, Col2)
I want to copy from ServerA.TableA to ServerB.TableB.
My code:
Truncate_table(ConnectionB, "TableB");
MySqlCommand CmdB = new MySqlCommand("", ConnectionB);
CmdB.CommandText = "INSERT INTO ServerB.TableB (col1, col2) VALUES (#val1, #val2)";
using (MySqlCommand cmd = new MySqlCommand("", ConnectionA))
{
cmd.CommandText = "SELECT col2, col3 FROM ServerA.TableA";
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
CmdB.Parameters.AddWithValue("#val1", reader.GetInt32(0));
CmdB.Parameters.AddWithValue("#val2", reader.GetInt32(1));
CmdB.ExecuteNonQuery();
}
}
}
However, it gives error saying 'Parameter '#val1' has already been defined.'.
Can you guys give me a piece of advice?
And is there more efficient way to do this? but I want to do this in C#.
Try adding the parameters once, then setting the value of those parameters within the while-loop:
MySqlCommand CmdB = new MySqlCommand("", ConnectionB);
CmdB.CommandText = "INSERT INTO ServerB.TableB (col1, col2) VALUES (#val1, #val2)";
CmdB.Parameters.AddWithValue("#val1", 0); // Default values
CmdB.Parameters.AddWithValue("#val2", 0);
using (MySqlCommand cmd = new MySqlCommand("", ConnectionA))
{
cmd.CommandText = "SELECT col2, col3 FROM ServerA.TableA";
using (MySqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
CmdB.Parameters["#val1"].Value = reader.GetInt32(0));
CmdB.Parameters["#val2"].Value = reader.GetInt32(1));
CmdB.ExecuteNonQuery();
}
}
}
Also, I could be wrong, but I believe you need to use ? to delimit parameters for MySql. If you have any other issues you might try replacing #val1 and #val2 with ?val1 and ?val2.
You are coping row by row the data. This is a very inefficient way to copy from a table to another. You can achieve the same result with a similar code executing just one INSERT on the database, you just need to read previously all the rows you want to insert.
Oh I just added
CmdB.Parameters.Clear();
After
CmdB.ExecuteNonQuery();
Related
SqlCeCommand command = new SqlCeCommand(#"INSERT INTO fpl_table
(FLIGHT_ID, BPN_TIME, BPX_TIME, DAY_NB)
VALUES (#FLIGHT_ID, #BPN_TIME, #BPX_TIME, #DAY_NB)
ON DUBLICATE UPDATE FLIGHT_ID = #FLIGHT_ID, BPN_TIME=#BPN_TIME,BPX_TIME=#BPX_TIME,DAY_NB=#DAY_NB"
,connection);
command.Parameters.AddWithValue("FLIGHT_ID", format);
command.Parameters.AddWithValue("BPN_TIME", format1);
command.Parameters.AddWithValue("BPX_TIME", format2);
command.Parameters.AddWithValue("DAY_NB", format3);
Hi everyone!
Ive got the problem with inserting 4 values into columns. I wanna prevent inserting 4 existing columns into database, i cant set them unique, cause the same column can be inserted with other 1,2 or 3 columns, i just wanna prevent only 4 existing columns insert.
you can add a unique constraint on 4 columns
CONSTRAINT UC_unique UNIQUE (col1, col2, col3, col4)
https://www.w3schools.com/sql/sql_unique.asp
Why not you use a seperate function to find out duplicate records at first.
bool CheckDuplicateFlight(int FLIGHT_ID)
{
SqlConnection con = new SqlConnection();
con.ConnectionString = #"YOURCONNECTION STRING";
con.Open();
if (con.State == System.Data.ConnectionState.Open)
{
SqlCeCommand cmd = new SqlCeCommand("select count(*) from YOURTABLE where FLIGHT_ID= #FLIGHT_ID", con);
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.AddWithValue("#FLIGHT_ID",FLIGHT_ID);
int ExistingId= Convert.ToInt32(cmd.ExecuteScalar());
}
con.Close();
if(ExistingId> 0)
return true;
return false;
}
if(CheckDuplicateFlight(FLIGHT_ID))
{
///// Your insertion/Update Code here
}
But Your Question is confusing a bit, Are you sure you want to insert record instead of update??? Insert query always inserts new record.
You need to add Unique Constraints to 3 columns, and than using exception handling at your code, insert new record.
I am trying to insert a large list of data in a MySQL table.
Due to performance issues, I'am filling a List<string> and with this list I generate my command string to do an unique insert with all my rows.
Here is my code:
StringBuilder cmdText = new StringBuilder("INSERT INTO my_Table (ColumnA, ColumnB) VALUES ");
List<string> aux = new List<string>();
using (MySqlConnection conn = new MySqlConnection(connString))
{
foreach (DataRow row in dataTable.Rows)
{
aux.Add(string.Format("('{0}','{1}')", row[0].ToString(), row[1].ToSTring()));
}
cmdText.Append(string.Join(",", aux));
cmdText.Append(";");
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(cmdText.ToString(), conn))
{
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 0;
cmd.ExecuteNonQuery();
};
This way, the result of my cmdText, finally is something like this:
INSERT INTO my_Table (ColumnA, ColumnB) VALUES ('Value1','Value2') ('Value3','Value4') ...;
with aproximately 500k rows in teh same insert.
One or more of this rows can contain values starting with '#'
I'm not using parameters ('#parameter'), but when I execute my application,
I get an error like this:
Fatal error encountered during command execution.
"Parameter '#GMAIL.COM' must be defined."
#gmail.com is a value, not a parameter. But it still been interpreted like a #parameter.
Anyone knows the way to indicate that this is not a param but a value??
I am writing a simple reporting tool that will need to move data from a table in one Access database to a table in another Access database (the table structure is identical). However, I am new to C# and am finding it hard to come up with a reliable solution.
Any pointers would be greatly appreciated.
Access SQL supports using an IN clause to specify that a table resides in a different database. The following C# code SELECTs rows from a table named [YourTable] in Database1.accdb and INSERTs them into an existing table named [YourTable] (with the identical structure) in Database2.accdb:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;
namespace oleDbTest
{
class Program
{
static void Main(string[] args)
{
string myConnectionString;
myConnectionString =
#"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source=C:\Users\Public\Database1.accdb;";
using (var con = new OleDbConnection())
{
con.ConnectionString = myConnectionString;
con.Open();
using (var cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText =
#"INSERT INTO YourTable IN 'C:\Users\Public\Database2.accdb' " +
#"SELECT * FROM YourTable WHERE ID < 103";
cmd.ExecuteNonQuery();
}
con.Close();
}
Console.WriteLine("Done.");
}
}
}
Many ways.
0) If it's only once, copy and paste the table.
1) If you want to do this inside Access, the easiest way is to create a linked table in the new database, and then a make table query in the new database.
2) You can reference the second table directly.
SELECT *
FROM TableInDbX IN 'C:\SomeFolder\DB X';
3) In a macro, you can use the TransferDatabase method of the DoCmd object to link relevant tables and then run suitable append and update queries to synchronize.
4) VBA
http://www.techonthenet.com/access/questions/new_mdb.php
Given column names Col1, Col2, and Col3:
private static void Migrate(string dbConn1, string dbConn2) {
// DataTable to store your info into
var table = new DataTable();
// Modify your SELECT command as needed
string sqlSelect = "SELECT Col1, Col2, Col3 FROM aTableInOneAccessDatabase ";
// Notice this uses the connection string to DB1
using (var cmd = new OleDbCommand(sqlSelect, new OleDbConnection(dbConn1))) {
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
cmd.Connection.Close();
}
// Modify your INSERT command as needed
string sqlInsert = "INSERT INTO aTableInAnotherAccessDatabase " +
"(Col1, Col2, Col3) VALUES (#Col1, #Col2, #Col3) ";
// Notice this uses the connection string to DB2
using (var cmd = new OleDbCommand(sqlInsert, new OleDbConnection(dbConn2))) {
// Modify these database parameters to match the signatures in the new table
cmd.Parameters.Add("#Col1", DbType.Int32);
cmd.Parameters.Add("#Col2", DbType.String, 50);
cmd.Parameters.Add("#Col3", DbType.DateTime);
cmd.Connection.Open();
foreach (DataRow row in table.Rows) {
// Fill in each parameter with data from your table's row
cmd.Parameters["#Col1"].Value = row["Col1"];
cmd.Parameters["#Col2"].Value = row["Col2"];
cmd.Parameters["#Col3"].Value = row["Col3"];
// Insert that data
cmd.ExecuteNonQuery();
}
cmd.Connection.Close();
}
}
Now, I do not work with Access databases very often, so you may need to tweak something up there.
That should get you well on your way, though.
Worth noting:
If I remember correctly, Access does NOT pay attention to your OleDbParameter names! You could call them whatever you want, and in fact most people just use a question mark ? for the parameter fields.
So, you have to add and update these parameters in the same order that your statement calls them.
So, why did I name the parameters #Col1, #Col2, #Col3? Here, it just to help you and me understand where each parameter is intended to map to. It is also good practice to get into. If you ever migrate to a better database, hopefully it will pay attention to what the parameters are named.
Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}
Using C# in Visual Studio, I'm inserting a row into a table like this:
INSERT INTO foo (column_name)
VALUES ('bar')
I want to do something like this, but I don't know the correct syntax:
INSERT INTO foo (column_name)
VALUES ('bar')
RETURNING foo_id
This would return the foo_id column from the newly inserted row.
Furthermore, even if I find the correct syntax for this, I have another problem: I have SqlDataReader and SqlDataAdapter at my disposal. As far as I know, the former is for reading data, the second is for manipulating data. When inserting a row with a return statement, I am both manipulating and reading data, so I'm not sure what to use. Maybe there's something entirely different I should use for this?
SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.
You can use SqlCommand.ExecuteScalar to execute the insert command and retrieve the new ID in one query.
using (var con = new SqlConnection(ConnectionString)) {
int newID;
var cmd = "INSERT INTO foo (column_name)VALUES (#Value);SELECT CAST(scope_identity() AS int)";
using (var insertCommand = new SqlCommand(cmd, con)) {
insertCommand.Parameters.AddWithValue("#Value", "bar");
con.Open();
newID = (int)insertCommand.ExecuteScalar();
}
}
try this:
INSERT INTO foo (column_name)
OUTPUT INSERTED.column_name,column_name,...
VALUES ('bar')
OUTPUT can return a result set (among other things), see: OUTPUT Clause (Transact-SQL). Also, if you insert multiple values (INSERT SELECT) this method will return one row per inserted row, where other methods will only return info on the last row.
working example:
declare #YourTable table (YourID int identity(1,1), YourCol1 varchar(5))
INSERT INTO #YourTable (YourCol1)
OUTPUT INSERTED.YourID
VALUES ('Bar')
OUTPUT:
YourID
-----------
1
(1 row(s) affected)
I think you can use ##IDENTITY for this, but I think there's some special rules/restrictions around it?
using (var con = new SqlConnection("connection string"))
{
con.Open();
string query = "INSERT INTO table (column) VALUES (#value)";
var command = new SqlCommand(query, con);
command.Parameters.Add("#value", value);
command.ExecuteNonQuery();
command.Parameters.Clear();
command.CommandText = "SELECT ##IDENTITY";
int identity = Convert.ToInt32(command.ExecuteScalar());
}