How to convert mysql query into acceptable c# string? - c#

Im creating columns using mysql dynamically if column doesnt exist.. I got the code which works in mysql console but when it comes to c# its giving me "Fatal encountered during command execution"
SET #preparedStatement = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tableName'
AND table_schema = DATABASE()
AND column_name = 'colName'
) > 0,
"SELECT 1",
"ALTER TABLE `tableName` ADD `colName` TINYINT(1) NULL DEFAULT '0';"
));
PREPARE alterIfNotExists FROM #preparedStatement;
EXECUTE alterIfNotExists;
DEALLOCATE PREPARE alterIfNotExists;
above code i converted into c# string as
string qry = "SET #preparedStatement = ( SELECT IF( (SELECT count(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'attendance' AND TABLE_NAME = '" + tname + "' AND COLUMN_NAME = '" + code + "_C' ) > 0, \"SELECT 1', \"ALTER TABLE " + tname + " ADD " + code + "_C int(3) NOT NULL default '0'; \" )); PREPARE alterIfNotExists FROM #preparedStatement; EXECUTE alterIfNotExists; DEALLOCATE PREPARE alterIfNotExists;";
what's the error getting?
Execution Code:
private void columnCreate_Load(object sender, EventArgs e)
{
string tname = "bca_i"; //for temprory
string code = "BCAXX";//for temprory
string qry = #"SET #preparedStatement = ( SELECT IF( (SELECT count(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'attendance' AND TABLE_NAME = '" + tname + "' AND COLUMN_NAME = '" + code + "_C' ) > 0, \"SELECT 1', \"ALTER TABLE " + tname + " ADD " + code + "_C int(3) NOT NULL default '0'; \" )); PREPARE alterIfNotExists FROM #preparedStatement; EXECUTE alterIfNotExists; DEALLOCATE PREPARE alterIfNotExists;";
try
{
using (MySqlConnection conn = new MySqlConnection(ConStr))
{
conn.Open();
using (MySqlCommand cmd = new MySqlCommand(qry, conn))
{
cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

The part
\"SELECT 1', \"A
does not match your original query at
"SELECT 1",
"A
Do you spot it? You replaced the " after 1 by an '.

I just figured other way for checking column exist.. Just used below query and checked if the column exists iterating through the loop of columns
string last_col = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'attendance' AND TABLE_NAME ='" + subCodeText.Text + "'";
where attendance is database and subCodeText.Text is my table name.

Related

String or binary data would be truncated. The statement has been terminated. when inserting into the table

In my application I am getting one row from table1 displaying it in the view and then after reply I am inserting the reply into table 2 and deleting the the entry from table 1 and getting the next question from table1.
I am getting the error:
String or binary data would be truncated. The statement has been terminated
in the httppost method. I have checked the values of the tempdata in the post method by applying a breakpoint and there is no problem with it.
The values in the database are of type nvarchar except the id which is of int type.
I am not able to find why I still get the error. The error shows in the execute method but I am not able to find the reason behind it.
The things that I am inserting are mostly strings and some may contain special character in the string like * , \ etc and up to 700 characters.
PS: Presently I have ignored SQL injection threat
[HttpGet]
public ActionResult Index()
{ string connstr = "Here is the connection string";
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
SqlCommand cmd = new SqlCommand(" Select top(1) Id , Body , Email_subject , Queue , Intent , Tagging FROM
table1 ");
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = conn;
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
var Did = reader["Id"].ToString();
TempData["id "] = Int64.Parse(Did);
TempData["subject "] = reader["Email_subject"].ToString();
TempData["body"] = reader["Body"].ToString();
TempData["intent"] = reader["Intent"].ToString();
TempData["queue"] = reader["Queue"].ToString();
TempData["tagging"] = reader["Tagging"].ToString();
}
conn.Close();
TempData.Keep();
return View();
}
[HttpPost]
public ActionResult Index(string Correctornot)
{ TempData.Keep();
string connstr = My connection String;
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
SqlCommand cmd = new SqlCommand("SET IDENTITY_INSERT table2 ON ; INSERT INTO table2 ( Id ,Body, Response ,Queue , Intent , Tagging , Email_subject) VALUES ( '" + TempData["id"] + "' , '" + TempData["body"] + "'
, '" + Correctornot + "' , '" + TempData["Queue"] + "' , '" + TempData["intent"] + "' , '" + TempData["tagging"] + "' , '" + TempData["subject"] + "');DELETE FROM table1 where Id = '" + TempData["id"] + "' ;");
cmd.CommandType = System.Data.CommandType.Text;
cmd.Connection = conn;
SqlDataReader reader2 = cmd.ExecuteReader();
SqlCommand cmd2 = new SqlCommand(" Select top(1) Id , Body , Email_subject , Queue , Intent , Tagging FROM table1");
cmd2.CommandType = System.Data.CommandType.Text;
cmd2.Connection = conn;
SqlDataReader reader3 = cmd2.ExecuteReader();
while (reader3.Read())
{
var Did = reader3["Id"].ToString();
TempData["id "] = Int64.Parse(Did);
TempData["subject "] = reader3["Email_subject"].ToString();
TempData["body"] = reader3["Body"].ToString();
TempData["intent"] = reader3["Intent"].ToString();
TempData["queue"] = reader3["Queue"].ToString();
TempData["tagging"] = reader3["Tagging"].ToString(); }
conn.Close();
TempData.Keep();
return View(); }
Solution:
I was able to solve the problem but I still don't know the reason behind it.
The problem was due to the value returned by clicking the button. Though the value was not too large ( it was just "correct " and "not correct") , when i tried to insert it into the database it gave me the error .
I solved it by using a switch statement instead of directly adding it to the insert statement.
i.e
switch (Correctornot)
{
case "Correct":
sql = "Insert INTO [dbo].[Labeler_Email_For_confirmation_Agents](Body , Response , Queue , Intent , Tagging , Email_subject ) Values ( '" + TempData["body"].ToString() + "' , 'yes' , '" + TempData["queue"].ToString() + "' , '" + TempData["intent"].ToString() + "' , '" + TempData["tagging"].ToString() + "' , '" + TempData["email_subject"].ToString() + "');";
break;
case "Not Correct":
sql = "Insert INTO [dbo].[Labeler_Email_For_confirmation_Agents](Body , Response , Queue , Intent , Tagging , Email_subject ) Values ( '" + TempData["body"].ToString() + "' , 'no' , '" + TempData["queue"].ToString() + "' , '" + TempData["intent"].ToString() + "' , '" + TempData["tagging"].ToString() + "' , '" + TempData["email_subject"].ToString() + "');";
break;
}
SQL Server 2016 SP2 CU6 and SQL Server 2017 CU12
introduced trace flag 460 in order to return the details of truncation warnings.
You can enable it at the query level or at the server level.
Query level
INSERT INTO dbo.TEST (ColumnTest)
VALUES (‘Test truncation warnings’)
OPTION (QUERYTRACEON 460);
GO
Server Level
DBCC TRACEON(460, -1);
GO
From SQL Server 2019 you can enable it at database level:
ALTER DATABASE database_name
SET COMPATIBILITY_LEVEL = 150
ALTER DATABASE SCOPED CONFIGURATION
SET VERBOSE_TRUNCATION_WARNINGS = ON;
The old output message is:
Msg 8152, Level 16, State 30, Line 13
String or binary data would be truncated.
The statement has been terminated.
The new output message is:
Msg 2628, Level 16, State 1, Line 30
String or binary data would be truncated in table 'DbTest.dbo.TEST', column 'ColumnTest'. Truncated value: ‘Test truncation warnings‘'.
In a future SQL Server 2019 release, message 2628 will replace message 8152 by default.
"String or binary data would be truncated. The statement has been terminated" is reporting that one of the values you are trying to insert is too large for the SQL Column. For example, you'll see this error if you try insert "Hello, World" into a SQL Column that can only hold 4 characters. Truncate the value before inserting, or change the datatype of the SQL Column.

Get RecordId from table

I am new to SQL, I have table with RecordId that is incremented automatically and is primary key. I would like to get RecordId of the row that was inserted into table.
Thanks in advance for help.
myCommand.CommandText = "INSERT INTO " + tableName + " (DateRaised,RaisedBy,WeekNo,Platform,Department,Site,Process, Area,NavErrorNo,RootCauseDescription,Status) " +
"VALUES ('" + currentDate.ToString(format) + "','" +
sender + "'," +
weekNumber + ",'" +
comboBoxPlatform.SelectedItem + "','" +
comboBoxDepartment.SelectedItem + "','" +
comboBoxSite.SelectedItem + "','" +
comboBoxProcess.SelectedItem + "','" +
comboBoxArea.SelectedItem + "','" +
textBoxNavError.Text + "','" +
textBoxIssue.Text + "','Open')";
//int lastInsertedId =
myCommand.ExecuteNonQuery();
lastInsertedId should be int from RecordId in my table.
To do this properly (if this is for SQL Server - you weren't very clear on this), I see two options:
Approach #1 - using SCOPE_IDENTITY
This works well if you're only ever inserting a single row at a time - use something like this:
// set up your query using *PARAMETERS** as you **ALWAYS** should!
// Using SELECT SCOPE_IDENTITY() to get back the newly inserted "Id"
myCommand.CommandText = "INSERT INTO dbo.SomeTable (list-of-columns) " +
"VALUES (#param1, #param2, #param3, ...., #paramN); " +
"SELECT SCOPE_IDENTITY();";
// set up the parameters and theirs values
object result = myCommand.ExecuteScalar();
if (result != null)
{
int lastInsertedId = Convert.ToInt32(result);
}
Approach #2 - using the OUTPUT clause
This works well even if you insert multiple rows at once (typically using a SELECT after the INSERT):
// set up your query using *PARAMETERS** as you **ALWAYS** should!
// Using SELECT SCOPE_IDENTITY() to get back the newly inserted "Id"
myCommand.CommandText = "INSERT INTO dbo.SomeTable (list-of-columns) " +
"OUTPUT Inserted.RecordId " +
"VALUES (#param1, #param2, #param3, ...., #paramN); ";
// set up the parameters and theirs values
object result = myCommand.ExecuteScalar();
if (result != null)
{
int lastInsertedId = Convert.ToInt32(result);
}
First thing this is not a good idea to call direct SQL statement from code it can cause an issue for SQL injection as #Zohar suggested.
You can either user parametrized query or sp.
Inside sp, you can use
SELECT ##IDENTITY AS 'Identity';
after Insert statement, it will return the last auto-incremented value for PK,
then return this value as an output parameter and catch it after .ExecuteNonQuery(); in C# code.
This should do the trick for You
private void SelectLast()
{
string sqlLast = "SELECT TOP(1) RecordId FROM [YourtableName] ORDER BY 1 DESC";
Connection.Open();
using (SqlCommand cmd = new SqlCommand(sqlLast, Connection))
{
cmd.CommandType = CommandType.Text;
{
int insertedID = Convert.ToInt32(cmdAdd.ExecuteScalar());
textBoxID.Text = Convert.ToString(insertedID);
}
Connection.Close();
}
}

Convert SQL to c# SQL query

Old SQL:
SELECT
[FileName], [FilePath]
FROM
dbo.[tb_CrawlData] cr
WHERE
cr.Content LIKE '%' + (SELECT content
FROM [tb_CrawlData]
WHERE Content LIKE '%test1%') + '%'
GROUP BY
cr.FileName, [FilePath]
ORDER BY
cr.FileName
Old C# SQL query:
Sqlquery = "SELECT [FileName], [FilePath]"
+ " FROM [tb_CrawlData] cr "
+ " WHERE cr.Content like '%' + (" + Sqlquery.Substring(Sqlquery.IndexOf(" SELECT") + 1) + ") + '%' ";
Sqlquery += " GROUP BY cr.FileName,[FilePath]"
+ " ORDER BY cr.FileName ";
New SQL:
select
[FileName], [FilePath]
from
dbo.[tb_CrawlData] cr
where exists (select 1
from [tb_CrawlData] cd
where cd.Content like '%data%'
and cr.Content like '%' + cd.Content + '%')
group by
cr.FileName, [FilePath]
order by
count(*) desc, cr.FileName
New C# SQL query:
The new sql, I am not so sure how to modify for c#.
We have to use the SqlCommand class.
string sql = "select
[FileName], [FilePath]
from
dbo.[tb_CrawlData] cr
where exists (select 1
from [tb_CrawlData] cd
where cd.Content like '%data%'
and cr.Content like '%' + cd.Content + '%')
group by
cr.FileName, [FilePath]
order by
count(*) desc, cr.FileName"
string connectionString = "Server=.\PDATA_SQLEXPRESS;Database=;User Id=sa;Password=2BeChanged!;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(sql, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
}
Use QueryFirst. You can run your SQL directly in your C# application.
disclaimer : which I wrote :-)

Migrate data from informix db to sqlserver db

I try to Migrate the data for list of employees from informix db to sqlserver2012 db ,so firstly i select
-The data from the tables in informix like this :
string cmdText = "select * from permission where emp_num in( " + emplyeeRange + " ) and perm_date>=? and perm_date <=?";
DataTable permissionDT = ifx_conn.Return_DataTable(cmdText, CommandType.Text, paramList1);
cmdText = "select * from holid where emp_num in( " + emplyeeRange + " ) and end_date>=? and start_date<=? ";
DataTable vacationDT = ifx_conn.Return_DataTable(cmdText, CommandType.Text, paramList1);
cmdText = "select * from empmission where emp_num in( " + emplyeeRange + " ) and date(to_date)>=? and date(from_date)<=? ";
DataTable missionDT = ifx_conn.Return_DataTable(cmdText, CommandType.Text, paramList1);
-Then i delete the data from sqlserver in the same range date like this :
cmdText = "delete from permission where emp_num in( " + emplyeeRange + " ) and perm_date>=#from_date and perm_date <=#to_date";
sql_command.CommandType = CommandType.Text;
sql_command.Parameters.AddWithValue("#from_date", from_date.ToShortDateString());
sql_command.Parameters.AddWithValue("#to_date", to_date.ToShortDateString());
sql_command.CommandText = cmdText;
result = sql_command.ExecuteNonQuery();
if (result >= 0)
{
cmdText = "delete from holid where emp_num in( " + emplyeeRange + " ) and end_date>=#from_date and start_date<=#to_date ";
sql_command.CommandText = cmdText;
result = sql_command.ExecuteNonQuery();
if (result >= 0)
{
cmdText = "delete from empmission where emp_num in( " + emplyeeRange + " ) and to_date>=#from_date and from_date<=#to_date";
sql_command.CommandText = cmdText;
result = sql_command.ExecuteNonQuery();
}
}
-Then Insert the updated data in sqlserver like this :
cmdText = "insert into permission select * from #permissionDT ";
sql_command.CommandText = cmdText;
sql_command.Parameters.Clear();
sql_param = sql_command.Parameters.AddWithValue("#permissionDT", permissionDT);
sql_param.SqlDbType = SqlDbType.Structured;
sql_param.TypeName = "dbo.permissionType";
result = sql_command.ExecuteNonQuery();
if (result >= 0)
{
cmdText = "insert into holid select * from #vacationDT";
sql_command.CommandText = cmdText;
sql_command.Parameters.Clear();
sql_param = sql_command.Parameters.AddWithValue("#vacationDT", vacationDT);
sql_param.SqlDbType = SqlDbType.Structured;
sql_param.TypeName = "dbo.holidType";
result = sql_command.ExecuteNonQuery();
if (result >= 0)
{
cmdText = "insert into empmission select * from #missionDT";
sql_command.CommandText = cmdText;
sql_command.Parameters.Clear();
sql_param = sql_command.Parameters.AddWithValue("#missionDT", missionDT);
sql_param.SqlDbType = SqlDbType.Structured;
sql_param.TypeName = "dbo.empmissionType";
result = sql_command.ExecuteNonQuery();
}
}
My Main problem is :
This process takes so long time and decrease the performance of sqlserver ,How to optimize this code and the queries concerning the db operations ?
Replace your SQLCommand ("insert into holid select * from #vacationDT") by SQLBulkCopy it will write you your server a lot faster.
e.g.:
using (var sbc = new SqlBulkCopy(myCOnnection)
{
sbc.DestinationTableName = "holid";
sbc.WriteToServer(vacationDT);
}
You may have to set ColumnMappings and/or set identity insert/on-off before and after this. More on SQLBulkCopy: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx
Also, check if your DB has all the right indexes especially on start_date and end_date

Drop table in teradata

I tried to drop a table in Teradata database with C# if the table exist.
cmd.CommandText = string.Format("IF EXISTS
(SELECT * FROM sysobjects WHERE type = 'U' AND name = '{0}')
BEGIN DROP TABLE '{0}' END", Customer.TableName);
cmd.ExecuteNonQuery();
But the above always failed with :
{"[Teradata Database] [3706] Syntax error: expected something between the beginning of the request and the 'IF' keyword."}
Second code i tried, the code below works !!!
cmd.CommandText = "select count (*) from Customer.TableName";
reader = cmd.ExecuteReader();
if (reader.FieldCount > 0)
{
reader.Close();
cmd.CommandText = "Drop table Customer.TableName";
reader = cmd.ExecuteReader();
}
However, it works only when got table exist. If the table Customer.TableName does not exist, then it will failed when undergo this
"select count (*) from Customer.TableName";
reader = cmd.ExecuteReader();
You can try
IF EXISTS(SELECT 1 FROM dbc.tables WHERE databasename = db_name
AND tablename = table_name) THEN DROP TABLE table_name
First Try this in editor and then place in your .net c# code.
This will ensure existence of the table and if it exists it will delete it.
Got it working with
"select count(*) from DBC.TABLES WHERE TABLENAME ='" + table.Split('.')[1] + "' and DatabaseName = '" + databasename+ "'"

Categories

Resources