How to update the full row if BatchNumber (in my case) exists?
In my table batch number is unique and I need to update the entire row or the quantity column if Batchnumber is exist
Please, help me to do this in a proper way
{
var conn = new SqlConnection(GetConnectionString());
var StrBuilder = new StringBuilder(string.Empty);
var splitItems = (string[])null;
foreach (string item in SC_PurLinr)
{
const string sqlStatement = "INSERT INTO DEL_Stores (DealerCode, Code, Qty, ExpireDate, BatchNumber) VALUES";
if (item.Contains(","))
{
splitItems = item.Split(",".ToCharArray());
StrBuilder.AppendFormat("{0}('{1}','{2}','{3}','{4}','{5}'); ", sqlStatement, splitItems[0], splitItems[1], splitItems[2], splitItems[3], splitItems[4]);
}
}
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(StrBuilder.ToString(), conn) { CommandType = CommandType.Text };
cmd.ExecuteNonQuery();
wucMessagePopup1.showPopup(1, string.Empty, "Record Saved Successfully.");
}
catch (SqlException ex)
{
}
finally
{
conn.Close();
}
}
Use MERGE from SQL Server 2008:
WITH new_rows (
SELECT #value value
,#BatchNumber BatchNumber)
MERGE DEL_Stores target
USING new_rows source ON source.BatchNumber = target.BatchNumber
WHEN MATCHED THEN
UPDATE SET value = #value
WHEN NOT MATCHED THEN
INSERT (
BatchNumber
,value)
VALUES(
source.BatchNumber
source.value);
You can achieve this by stored procedure in better way.
Your procedure should be like this.
create PROCEDURE usp_Namae
#parmeter INT
,#parmeter INT
,#BatchNumber INT
AS
BEGIN
IF NOT EXISTS (
SELECT *
FROM tblname
WHERE BatchNumber = #BatchNumber
)
BEGIN
--INSERT query
END
ELSE
BEGIN
--Update query
END
END
Just add IF statement before insert data as below:
IF EXISTS (select * from sys.columns where object_id = OBJECT_ID(N'DEL_Stores') and name='BatchNumber')
BEGIN
// Do insert here
END
Related
C#:
protected void btnsearch_Click(object sender, EventArgs e)
{
SqlConnection con = Connection.DBconnection(); {
SqlCommand com = new SqlCommand("sp_studentresult", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#id", textstudentid.Text);
com.Parameters.AddWithValue("#id_student", textstudentid.Text.Trim());
SqlParameter retval = new SqlParameter("#output", SqlDbType.VarChar, 50);
com.Parameters.AddWithValue("#tamil", txttamil.Text.Trim());
com.Parameters.AddWithValue("#english", txtenglish.Text.Trim());
com.Parameters.AddWithValue("#maths", txtmaths.Text.Trim());
com.Parameters.AddWithValue("#science", txtscience.Text.Trim());
com.Parameters.AddWithValue("#socialScience", txtsocialscience.Text.Trim());
retval.Direction = ParameterDirection.Output;
com.Parameters.Add(retval);
com.ExecuteNonQuery();
string Output = retval.Value.ToString();
textstudentid.Text = string.Empty;
txttamil.Text = string.Empty;
txtenglish.Text = string.Empty;
txtmaths.Text = string.Empty;
txtscience.Text = string.Empty;
txtsocialscience.Text = string.Empty;
SqlDataAdapter adp = new SqlDataAdapter(com);
DataSet ds = new DataSet();
adp.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
tblid.Visible = true;
txtid.Text = ds.Tables[0].Rows[0]["id"].ToString();
txttamil.Text = ds.Tables[0].Rows[0]["Tamil"].ToString();
txtenglish.Text = ds.Tables[0].Rows[0]["English"].ToString();
txtmaths.Text = ds.Tables[0].Rows[0]["Maths"].ToString();
txtscience.Text = ds.Tables[0].Rows[0]["Science"].ToString();
txtsocialscience.Text = ds.Tables[0].Rows[0]["SocialScience"].ToString();
}
else
{
tblid.Visible = false;
output.Text = Output;
}
}
What I have done:
Step 1
When I enter invalid id (which means id doesnot contain in student table) and search, it shows "doesn't exist".
Step 2
When I enter valid id (which means id contains in student and also contain in studentresult table) and search, it shows student marks, if I want to edit the marks and update, so it shows "marks updated".
Step 3
But when I enter id (which means id contains in student but doesn't contain in studentresult table) and search, it works updated function again with all the textboxes contains 0, instead it works insertion.
May I know, what my mistake in the above code?
Can anyone guide me?
I'm struggling for an hour, I'm beginner in .net.
Thanks,
sp_studentresult is broken: it should not insert into studentresult if there already is a row for the given id. Just add
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
to
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
Resulting to:
ALTER PROCEDURE sp_studentresult
(
#id int,
#output varchar(50) output,
#id_student varchar(50),
#Tamil Varchar (100),
#English varchar (50),
#Maths Varchar (50),
#Science Varchar (50),
#SocialScience Varchar (50)
)
AS
IF NOT EXISTS (SELECT * FROM student WHERE id=#id_student)
BEGIN
SET #output='Doesn not EXIST'
END
ELSE IF EXISTS (SELECT * FROM student WHERE id=#id_student)
AND NOT EXISTS (SELECT * FROM studentresult WHERE id_student=#id_student)
BEGIN
INSERT into studentresult (id_student,Tamil,English,Maths,Science,SocialScience) values (#id_student,#Tamil,#English,#Maths,#Science,#SocialScience)
SET #output='Inserted'
END
SELECT * from studentresult where id_student=#id
in a c# application, I need to insert into sql server 2005 table a lot or records. I split datatable in 2000 records chunk, using linq to sql server but dont work good becasue dont stop ever! I've 900.000 recors and insert a lot more thant this. What I'm doing wrong?
This is my code:
int jump = 0;
while (ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1)
{
String xmlData = ConvertDataTableToXML(ds.Tables[0].AsEnumerable().Skip(jump).Take(2000 + jump).CopyToDataTable());
jump = jump + 2001;
SqlConnection conn = new SqlConnection
("Data Source=SERVER;Initial Catalog=DATABASE;Persist Security Info=True;User ID=USER;Password=PASS;");
conn.Open();
SqlCommand insert = new SqlCommand
("sp_InsertData'" + xmlData + "'", conn);
insert.ExecuteNonQuery();
conn.Close();
}
if you understand Temp Tables in SQL Server as well as how to use the OPENXML command you can try the following. it works even if your DBA disables BULK INSERTS
substitute my field names with your own and the field mappings in this portion of the code should match your tables schema / field definitions / data types
FROM OPENXML (#xmlHandle, '/NewDataSet/XMLDataTable',1)
WITH (
ALTER PROCEDURE [dbo].[sp_InsertData]
(#xmlString VARCHAR(MAX))
AS
BEGIN
/* Initialize a handle for the XmlDocument */
DECLARE #xmlHandle INT
/*
Created by #MethodMan you first want to create / declare a TEMP TABLE which
Mimic's the structure of the Target table that you are inserting into
*/
DECLARE #someTargetTable TABLE
(
[EN_INTFC_ID] varchar(25),
[EN_INTFC_LINE_NUM] varchar(5),
[EN_BILL_SOURCE_ID] varchar(10),
[EN_BUSINESS_UNIT] varchar(12),
[EN_ASSET_NAME] varchar(4),
[EN_POSTING_DATE] DateTime,
[EN_FISCAL_YEAR] varchar(4),
[EN_FISCAL_PERIOD] varchar(3),
[EN_CUSTOMER_ID] varchar(50),
[EN_DOC_TYPE] varchar(4),
[EN_TARGET_INVOICE] varchar(16),
[EN_INVOICE_DT] DateTime,
[EN_REVNUE_TYPE] varchar(15),
[EN_QTY] decimal(15,0),
[EN_GROSS_EXT_AMT] decimal(25,2),
[EN_DESCR] varchar(50),
[EN_CONTRACT] varchar(20),
[EN_PRODUCT_TYPE] varchar(15),
[EN_UNIT_OF_MEASURE] varchar(3)
)
/*
Create the XmlDocument using the handle above and the Xml
string as parameters. If your stored procedure has an varchar input
parameter named #xmlString, it would look like this instead:
EXEC sp_xml_preparedocument #xmlHandle output,#xmlString
*/
EXEC sp_xml_preparedocument #xmlHandle output, #xmlString
/*
Use the OPENXML method to query the XmlDocument starting at
/NewDataSet/SampleDataTable node.
*/
INSERT INTO #someTargetTable
SELECT [EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE]
FROM OPENXML (#xmlHandle, '/NewDataSet/XMLDataTable',1)
WITH (
[EN_INTFC_ID] varchar(25) '#EN_INTFC_ID',
[EN_INTFC_LINE_NUM] varchar(5) '#EN_INTFC_LINE_NUM',
[EN_BILL_SOURCE_ID] varchar(10) '#EN_BILL_SOURCE_ID',
[EN_BUSINESS_UNIT] varchar(12) '#EN_BUSINESS_UNIT',
[EN_ASSET_NAME] varchar(4) '#EN_ASSET_NAME',
[EN_POSTING_DATE] DateTime '#EN_POSTING_DATE',
[EN_FISCAL_YEAR] varchar(4) '#EN_FISCAL_YEAR',
[EN_FISCAL_PERIOD] varchar(3) '#EN_FISCAL_PERIOD',
[EN_CUSTOMER_ID] varchar(50) '#EN_CUSTOMER_ID',
[EN_DOC_TYPE] varchar(4) '#EN_DOC_TYPE',
[EN_TARGET_INVOICE] varchar(16) '#EN_TARGET_INVOICE',
[EN_INVOICE_DT] DateTime '#EN_INVOICE_DT',
[EN_REVNUE_TYPE] varchar(15) '#EN_REVNUE_TYPE',
[EN_QTY] decimal(15,0) '#EN_QTY',
[EN_GROSS_EXT_AMT] decimal(25,2) '#EN_GROSS_EXT_AMT',
[EN_DESCR] varchar(50) '#EN_DESCR',
[EN_CONTRACT] varchar(20) '#EN_CONTRACT',
[EN_PRODUCT_TYPE] varchar(15) '#EN_PRODUCT_TYPE',
[EN_UNIT_OF_MEASURE] varchar(3) '#EN_UNIT_OF_MEASURE'
)
/*Insert the records into the table variable */
INSERT INTO Your_Actual_Table_Name (
[EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE] )
(SELECT [EN_INTFC_ID],
[EN_INTFC_LINE_NUM],
[EN_BILL_SOURCE_ID],
[EN_BUSINESS_UNIT],
[EN_ASSET_NAME],
[EN_POSTING_DATE],
[EN_FISCAL_YEAR],
[EN_FISCAL_PERIOD],
[EN_CUSTOMER_ID],
[EN_DOC_TYPE],
[EN_TARGET_INVOICE],
[EN_INVOICE_DT],
[EN_REVNUE_TYPE],
[EN_QTY],
[EN_GROSS_EXT_AMT],
[EN_DESCR],
[EN_CONTRACT],
[EN_PRODUCT_TYPE],
[EN_UNIT_OF_MEASURE]
FROM #someTargetTable)
/* Remove the document from memory */
EXEC sp_xml_removedocument #xmlHandle
END
// your sql command below.
SqlCommand insert = new SqlCommand ("sp_InsertData '" + xmlData + "'", conn);
insert.CommandTimeout = 5000;
insert.ExecuteNonQuery();
conn.Close()
// my code and how you can utilize the using(){} statement along with code to convert a DataTable to XML then pass that xml to the stored procedure which I have depicted above
private bool ProcessSomeDataTableToXML(DataTable dataTable)
{
String xmlData = ConvertDataTableToXML(dataTable);
var ConnString = System.Configuration.ConfigurationManager.ConnectionStrings["yourdatabase"].ConnectionString;
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand command = new SqlCommand("sp_InsertData '" + xmlData + "'", connection))
{
connection.Open();
try
{
command.ExecuteNonQuery();
fileInserted = true;
}
catch (SqlException sqlEx)
{
fileInserted = false;
Console.WriteLine(sqlEx.Message);
}
}
}
return fileInserted;
}
private static string ConvertDataTableToXML(DataTable dtData)
{
DataSet dsData = new DataSet();
StringBuilder sbSQL;
StringWriter swSQL;
string XMLformat;
try
{
sbSQL = new StringBuilder();
swSQL = new StringWriter(sbSQL);
dsData.Merge(dtData, true, MissingSchemaAction.AddWithKey);
dsData.Tables[0].TableName = "XMLDataTable";
foreach (DataColumn col in dsData.Tables[0].Columns)
{
col.ColumnMapping = MappingType.Attribute;
}
dsData.WriteXml(swSQL, XmlWriteMode.WriteSchema);
XMLformat = sbSQL.ToString();
sbSQL = null;
swSQL = null;
return XMLformat;
}
catch (Exception sysException)
{
throw sysException;
}
}
An obvious problem is in your while condition:
ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1
i.e. count < count + 1
i.e. true
Your loop is designed never to stop. You might change it to
while (jump < ds.Tables[0].Rows.Count)
1) You have an infite loop (ds.Tables[0].Rows.Count < ds.Tables[0].Rows.Count + 1)
2) Connection management: You don't need to open an close the connection on each iteration. Use a using block for disposing the connection once you are done with it.
I have a list with two columns in it: ID; int, Score: Double.
In addition, I have a table in SQL SERVER with several columns.One of them is id:int.
I want to have a query like below:
select * from tbl where id = id s in my list.
My codes are below:
protected void btnfind_Click(object sender, EventArgs e)
{
List<KeyValuePair<int, double>> candidatelist = CalculateScores();
FinalMatch(candidatelist);
BindGrid(cmd2);//Contains codes for filling grid view with cmd2 , sql data reader
}
protected void FinalMatch(List<KeyValuePair<int, double>> finallist)
{
DataTable tvp = new DataTable();
tvp = ConvertToDatatable(finallist);
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.CommandText = "dbo.DoSomethingWithCandidates";
SqlParameter tvparam = cmd2.Parameters.AddWithValue("#List", tvp);
tvparam.SqlDbType = SqlDbType.Structured;
cmd2.Connection = ClsDataBase.con;
}
protected DataTable ConvertToDatatable(List<KeyValuePair<int, double>> finallist)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Score");
foreach (var item in finallist)
{
var row = dt.NewRow();
row["ID"] = item.Key;
row["Score"] = item.Value;
dt.Rows.Add(row);
}
return dt;
}
protected void BindGrid(SqlCommand cmd)
{
if (ClsDataBase.con.State == ConnectionState.Closed)
ClsDataBase.con.Open();
SqlDataReader dr1 = cmd.ExecuteReader();
try
{
if (dr1.HasRows)
{
gv_allresults.DataSource = dr1;
gv_allresults.DataBind();
}
else
{
Response.Write("<script LANGUAGE='JavaScript' >alert('No Match')</script>");
}
if (dr1.IsClosed == false) dr1.Close();
}
catch (SqlException ex)
{
Response.Write("<script language='javascript'>alert(\"" + ex.ToString() + "\")</script>");
}
catch (Exception ex)
{
Response.Write("<script language='javascript'>alert(\"" + ex.ToString() + "\")</script>");
}
finally
{
ClsDataBase.con.Close();
}
}
And my codes in SQL server are:
CREATE TYPE dbo.CandidateList
AS TABLE
(
ID INT,
Score FLOAT
);
GO
CREATE PROCEDURE dbo.DoSomethingWithCandidates
#List AS dbo.CandidateList READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT ID FROM #List;
END
GO
I don't get the result. My procedure's codes are not complete. I don`t know what to do. Please help me.
Thanks so much.
Edited codes according to given suggestion:
protected void FinalMatch(List<KeyValuePair<int, double>> finallist)
{
int[] canArr = finallist.Select(x => x.Key).ToArray();
string csv = string.Join(",", canArr);
cmd2.CommandType = CommandType.StoredProcedure;
cmd2.CommandText = "dbo.ReturnCandidates";
cmd2.Parameters.AddWithValue("#LIST", csv);
cmd2.Connection = ClsDataBase.con;
}
And new codes in Sql server are:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CSVToTable] (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
GO
CREATE PROCEDURE dbo.ReturnCandidates
(
#LIST VARCHAR(200)
)
AS
BEGIN
SELECT *
FROM tblspecifications
WHERE id IN ( SELECT * FROM dbo.CSVToTable(#LIST) )
END
I get this error: "Procedure or function ReturnCandidates has too many arguments specified",
In below line:
SqlDataReader dr1 = cmd.ExecuteReader();
Please help me. Thanks a lot
I see cmd2.ExecuteNonQuery() missing.
Also, why not make a comma separated list of ID's and then send it to the SQL function. Example
int[] canArr= candidatelist.Select(x => x.Key).ToArray();
string csv = string.Join(",", canArr);
EDIT:
I created a SQL Fiddle for your query. It works.
http://sqlfiddle.com/#!6/c3d013/1/1
i have a string that contain a sql command,
something like this:
strCommand = "Select [Feild1],
[Feild2]
From TableName
Order By [Feild1] desc" ;
How can find table name in this string?
The solutions so far have all gone with the searching within strings approach. You've not mentioned if your SQL queries will always look similar, but there are many variants of a query to include which these solutions will break on. Consider...
SELECT Field1, Field2 FROM TableName
SELECT Field1, Field2 FROM [TableName]
SELECT Field1, Field2 FROM dbo.TableName
SELECT Field1, Field2 FROM Table1Name, Table2Name
If the query you're trying to parse is one you have the database for, you can get SQL server to do the hard work of parsing the query for you, instead of trying to account for all the cases in SQL. You can execute a query using SET SHOWPLAN_ALL ON, which will produce a table of the query plan. You can then analyse the Arguments column, which contains all of the fields the query will involve in a standard format. An example program is below:
SqlConnection conn = new SqlConnection(CONNECTIONSTRING);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SET SHOWPLAN_ALL ON";
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT [Field1], [Field2] FROM [TableName]";
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
Regex objectRegex = new Regex(#"^OBJECT:\(\[(?<database>[^\]]+)\]\.\[(?<schema>[^\]]+)\]\.\[(?<table>[^\]]+)\]\.\[(?<field>[^\]]+)\]\)$", RegexOptions.ExplicitCapture);
List<string> lstTables = new List<string>();
foreach (DataRow row in dt.Rows)
{
string argument = row["Argument"].ToString();
if (!String.IsNullOrEmpty(argument))
{
Match m = objectRegex.Match(argument);
if (m.Success)
{
string table = m.Groups["schema"] + "." + m.Groups["table"];
if (!lstTables.Contains(table))
{
lstTables.Add(table);
}
}
}
}
Console.WriteLine("Query uses the following tables: " + String.Join(", ", lstTables));
This will deal with all forms of query name and return all tables which are involved in the query, no matter how they are included.
If this is the same pattern all of the time then:
string tableName = strCommand.Split(' ', strCommand)[4];
but if you can add / remove fields just iterate through the splitted string and search for "From", and the next string will be your table name
I would say- what is after "From" as a more reliable way of getting the table name. Loop through the array created, when you reach "From", the next one is the table.
This is the Method which gives us tablename just change the SQL query string, connection String
Works with simple query, joins too
public static List<string> getTablenames(string connString, string QueryString)
{
SqlConnection con = new SqlConnection(connString);
con.Open();
DataTable dt = con.GetSchema("Tables");
List<string> getTableName = new List<string>();
List<string> tablenames = new List<string>();
foreach (DataRow dr in dt.Rows)
tablenames.Add(dr[2].ToString());
for (int i = 0; i < dt.Rows.Count; i++)
{
string myTable = tablenames[i];
Boolean checkMyTable = QueryString.Contains(myTable);
if (checkMyTable == true)
getTableName.Add(myTable);
}
con.Close();
return getTableName;
}
You can use the substring (This way it does not matter how many column you have to select)
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[0];
ISun's answer met my needs but one change is required to get the table name:
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[1];
not
string table = strCommand.ToLower().Substring(strCommand.IndexOf("FROM".ToLower())).Split(' ')[0];
If you want a solution in SQL, try this
declare #q varchar(1000) = 'Select [Feild1], [Feild2] From TableName Order By [Feild1] desc',
#tableName varchar(100) = '',
#temp varchar(1000),
#temp2 char(1)
declare #frmIndex int = CHARINDEX('From', #q, 0);
declare #flag int = 0, #counter int = 1;
select #temp = SUBSTRING(#q, #frmIndex, len(#q))
set #temp = LTRIM(REPLACE(#temp,'From',''))
while(#flag <> 1)
begin
set #temp2 = SUBSTRING(#temp, #counter, 1)
if(#temp2 = ' ')
set #flag = 1
select #tableName = #tableName + #temp2
set #counter = #counter + 1
end
select #tableName as TableName
I have a classic ASP site, that I am slowly upgrading. I would like to create a function to securely update a SQL database without specifying parameters manually. Something just a tad more dynamic.
(I do not want to use entity framework or Linq)
Here is the code so far:
string updateSql = "UPDATE sometable" + "SET test1= #testData1 " + "WHERE a = #aData1";
SqlCommand UpdateCmd = new SqlCommand(updateSql, conn);
UpdateCmd.Parameters.Add("#testData1 ", SqlDbType.NVarChar, 10, "testData1 ");
UpdateCmd.Parameters.Add("#aData1", SqlDbType.NVarChar, 20, "aData1");
UpdateCmd.Parameters["#testData1 "].Value = "21515";
UpdateCmd.Parameters["#aData1"].Value = "32t3t";
UpdateCmd.ExecuteNonQuery();
pseudo-code (what I would like to achieve)
Create an Ilist covering all variables {get; set:} [validate type/length here]
For every variable that contains a value (without validation issues) create sql update string.
Execute it.
Possible problem:
The only problem I can foresee, is that the list may have 500 variables, but each SQL update may only have only 2 or 3 columns being updated. Is this not efficient?
you need to do something like this....needs more coding obviously....
static void Main(string[] args)
{
var values = new Dictionary<string, object>( );
values.Add( "name", "timmerz" );
values.Add( "dob", DateTime.Now );
values.Add( "sex", "m" );
SqlUpdate( "sometable", values );
}
public static void SqlUpdate( string table, Dictionary<string,object> values, string where )
{
var equals = new List<string>( );
var parameters = new List<SqlParameter>( );
var i = 0;
foreach( var item in values )
{
var pn = "#sp" + i.ToString( );
equals.Add( string.Format( "{0}={1}", item.Key, pn ) );
parameters.Add( new SqlParameter( pn, item.Value ) );
i++;
}
string command = string.Format( "update {0} set {1} where {2}", table, string.Join( ", ", equals.ToArray( ) ), where );
var sqlcommand = new SqlCommand(command);
sqlcommand.Parameters.AddRange(parameters.ToArray( ) );
sqlcommand.ExecuteNonQuery( );
}
I'm not sure I fully understand what you're trying to do, but this might be close to what you're looking for. You can create an arbitrarily long list of parameters and respective values, then build the corresponding UPDATE dynamically from that list.
//set up SqlCommand
SqlCommand UpdateCmd = new SqlCommand();
UpdateCmd.Connection = conn;
//build your dictionary (probably happens elsewhere in your code)
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("col1", "col1 value");
parameters.Add("col2", 42);
parameters.Add("col3", DateTime.Now);
//build a command string and add parameter values to your SqlCommand
StringBuilder builder = new StringBuilder("UPDATE sometable SET ");
foreach(KeyValuePair<string, object> parameter in parameters) {
builder.Append(parameter.Key).Append(" = #").Append(parameter.Key).Append(",");
UpdateCmd.Parameters.AddWithValue("#" + parameter.Key, parameter.Value);
}
builder.Remove(builder.Length - 1,1);
//set the command text and execute the command
UpdateCmd.CommandText = builder.ToString();
UpdateCmd.ExecuteNonQuery();
If you are using SQL Server 2008 you have the option of passing in the parameters and their values as a table to a Stored Procedure.
Inside the Stored Procedure you can join the table to be updated with the table passed in. That would probably be more efficient than creating hundreds of sep update statements.
Here is a link that may help http://msdn.microsoft.com/en-us/library/bb675163.aspx
And here is some sample code based on the code you posted in your question
First Create a table to play with and populate it with some data
CREATE TABLE [dbo].[sometable](
[Test1] [nvarchar](100) NULL,
[a] [nvarchar](100) NULL
) ON [PRIMARY]
Insert sometable Select 'rerere', '122342'
Insert sometable Select 'sfsfw', '343'
Insert sometable Select 'sfdrgss', '434545'
Insert sometable Select 'srgegrgeg', '3939932'
Then Create the Type in SQL Server
Create TYPE dbo.ParamsType AS TABLE
( Test1 nvarchar(100), a nvarchar(100) )
Then Create the Stored Procedure that accepts the type as a parameter
CREATE PROCEDURE usp_UpdateSomeTable
#Parameters dbo.ParamsType READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE sometable
SET sometable.Test1 = p.Test1
FROM sometable INNER JOIN #Parameters as p
ON sometable.a = p.a;
END
GO
To test from SQL Server Management Studio you can run
Declare #t as ParamsType
Insert #t Select 'newValue1', '122342'
Insert #t Select 'morenew ', '343'
Insert #t Select 'again', '434545'
Insert #t Select 'OnceMore', '3939932'
exec usp_UpdateSomeTable #Parameters=#t
To Test from C# Try
static void Main(string[] args)
{
System.Data.DataTable YourData = new DataTable("Parameters");
DataColumn column;
DataRow row;
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "Test1";
YourData.Columns.Add(column);
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "a";
YourData.Columns.Add(column);
row = YourData.NewRow();
row["Test1"] = "newValue1";
row["a"] = "122342";
YourData.Rows.Add(row);
row = YourData.NewRow();
row["Test1"] = "morenew";
row["a"] = "343";
YourData.Rows.Add(row);
row = YourData.NewRow();
row["Test1"] = "again";
row["a"] = "434545";
YourData.Rows.Add(row);
SqlConnectionStringBuilder connString = new SqlConnectionStringBuilder();
connString.DataSource = "127.0.0.1";
connString.InitialCatalog = "SO";
connString.IntegratedSecurity = true;
using (SqlConnection conn = new SqlConnection())
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "usp_UpdateSomeTable";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter p = cmd.Parameters.AddWithValue("#Parameters", YourData);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "dbo.ParamsType";
cmd.Connection = conn;
conn.ConnectionString = connString.ConnectionString;
conn.Open();
cmd.ExecuteNonQuery();
}
}