I am using the following Code to execute the SP of MySql and get the output value. I need to get the output value to my c# after SP is executed. How ? Thanks.
Code :
public static string GetInsertStatement(string DBName, string TblName, string ColName, string ColValue)
{
string strData = "";
MySqlConnection conn = new MySqlConnection(ConfigurationSettings.AppSettings["Con_Admin"]);
MySqlCommand cmd = conn.CreateCommand();
try
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "InsGen";
cmd.Parameters.Clear();
cmd.Parameters.Add("in_db", MySqlDbType.VarChar, 20);
cmd.Parameters["in_db"].Value = DBName;
cmd.Parameters.Add("in_table", MySqlDbType.VarChar, 20);
cmd.Parameters["in_table"].Value = TblName;
cmd.Parameters.Add("in_ColumnName", MySqlDbType.VarChar, 20);
cmd.Parameters["in_ColumnName"].Value = ColName;
cmd.Parameters.Add("in_ColumnValue", MySqlDbType.VarChar, 20);
cmd.Parameters["in_ColumnValue"].Value = ColValue;
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
return strData;
}
SP :
DELIMITER $$
DROP PROCEDURE IF EXISTS `InsGen` $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `InsGen`
(
in_db varchar(20),
in_table varchar(20),
in_ColumnName varchar(20),
in_ColumnValue varchar(20)
)
BEGIN
declare Whrs varchar(500);
declare Sels varchar(500);
declare Inserts varchar(2000);
declare tablename varchar(20);
declare ColName varchar(20);
set tablename=in_table;
# Comma separated column names - used for Select
select group_concat(concat('concat(\'"\',','ifnull(',column_name,','''')',',\'"\')'))
INTO #Sels from information_schema.columns where table_schema=in_db and table_name=tablename;
# Comma separated column names - used for Group By
select group_concat('`',column_name,'`')
INTO #Whrs from information_schema.columns where table_schema=in_db and table_name=tablename;
#Main Select Statement for fetching comma separated table values
set #Inserts=concat("select concat('insert into ", in_db,".",tablename," values(',concat_ws(',',",#Sels,"),');')
from ", in_db,".",tablename, " where ", in_ColumnName, " = " , in_ColumnValue, " group by ",#Whrs, ";");
PREPARE Inserts FROM #Inserts;
select Inserts;
EXECUTE Inserts;
END $$
DELIMITER ;
Using output query parameter.
http://msdn.microsoft.com/en-us/library/59x02y99(VS.71).aspx
If I'm not mistaken instead of
cmd.ExecuteNonQuery();
there is an "ExecuteScalar" which will return a Scalar value.
The problem is that you're calling
cmd.ExecuteNonQuery();
That executes without reading back results.
Have a look at the documentation for Command, especially the methods that start with Execute, and decide which one's best for you
Related
I am trying to count how many users is updated and how many users are inserted after I run my stored procedure.
CREATE PROCEDURE [dbo].[ADProcTemp]
#Username varchar(250),
#DisplayName varchar(70),
#isEnabled tinyint,
#PassNevExp tinyint,
#addedUser int OUTPUT,
#updatedUser int OUTPUT
AS
BEGIN
SET #addedUser = 0
SET #updatedUser = 0
IF NOT EXISTS (SELECT TOP 1 PrezimeIme FROM [dbo].[tblZaposleni_AD] WITH (NOLOCK)
WHERE NetworkLogin = #Username)
BEGIN
IF(#isEnabled = 1 OR #PassNevExp = 1)
INSERT INTO [dbo].[tblZaposleni_AD](NetworkLogin, PrezimeIme, Status, PassNevExp)
VALUES (#Username, #DisplayName, #isEnabled, #PassNevExp)
SET #addedUser = #addedUser + ##ROWCOUNT;
SELECT #addedUser As UkupnoDodanihKorisnika
END
ELSE
BEGIN
UPDATE [dbo].[tblZaposleni_AD]
SET Status = #isEnabled,
PassNevExp = #PassNevExp
WHERE NetworkLogin = #Username
AND (Status <> #isEnabled) OR (PassNevExp <>#PassNevExp)
SET #updatedUser = #updatedUser + ##ROWCOUNT;
SELECT #updatedUser As UkupnoIzmjenjenihKorisnika
END
END
Here is my stored procedure and right now I want in my C# code display #addedUser and #updatedUser variable from stored procedure.
So far I create this
public void ExcStrPrc(string Username, string DisplayName, bool isEnable, bool PassNevExp)
{
SqlConnection conn = new SqlConnection(#"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=DesignSaoOsig1;Integrated Security=True");
SqlCommand cmd = new SqlCommand("ADProcTemp", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Username", Username.ToString().Trim());
cmd.Parameters.AddWithValue("#DisplayName", DisplayName.ToString().Trim());
cmd.Parameters.AddWithValue("#isEnabled", Convert.ToInt32(isEnable));
cmd.Parameters.AddWithValue("#PassNevExp", Convert.ToInt32(PassNevExp));
cmd.Parameters.Add("#addedUser", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#updatedUser", SqlDbType.Int).Direction = ParameterDirection.Output;
conn.Open();
int k = cmd.ExecuteNonQuery();
if (k != 0)
{
Console.WriteLine("Uspjesno izvrseno !");
}
Console.WriteLine("Ukupno novih korisnika {0}");
conn.Close();
}
Any idea how to display counter from stored procedure to C# function? I added inside my function and right now I didn't get any data in output...
TBH was a long time ago since I messed around with output parameters, but you add output parameters, but you never check those. The values you require should be in those parameters.
I suggest you try to get those values like (after the execution of course):
var addedUserCount = (int)cmd.Parameters["#addedUser"].Value;
Or something similar
Issue
We are in the process of changing a database name on our server, but the database is huge and we want to create a small application that will loop through all databases, and then all the tables in the databases and then all the columns in the tables for text that matches "LIVE".
Code
I started creating code but i feel like this way in clunky and is returning an error.
using (SqlConnection connection = new SqlConnection(#"data source="SERVER NAME";integrated security=false;uid="USER";password="PASSWORD";"))
{
connection.Open();
SqlCommand command = new SqlCommand(#"SELECT * FROM sys.databases", connection);
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
_databases.Add(string.Format("{0}", reader["name"]));
}
}
finally
{
reader.Close();
}
foreach (var database in _databases)
{
using (SqlConnection tableconnection = new SqlConnection(string.Format(#"data source="SERVER NAME";initial catalog=" + database + ";integrated security=false;uid="USERNAME";password="PASSWORD";")))
{
tableconnection.Open();
SqlCommand tablecommand = new SqlCommand(#"SELECT * FROM information_schema.tables", tableconnection);
SqlDataReader readertable = tablecommand.ExecuteReader();
try
{
while (readertable.Read())
{
_tables.Add(string.Format("{0}", readertable["TABLE_NAME"]));
}
}
finally
{
readertable.Close();
}
foreach (var tables in _tables)
{
SqlCommand columncommand = new SqlCommand(string.Format(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection));
SqlDataReader readercolumn = columncommand.ExecuteReader();
try
{
while (readercolumn.Read())
{
_columns.Add(string.Format("{0}", readercolumn["COLUMN_NAME"]));
}
}
finally
{
readercolumn.Close();
}
}
}
}
}
As you can see I am unsure if this is the best way to do it. The code errors on:
SqlDataReader readercolumn = columncommand.ExecuteReader();
and the error is:
Additional information: ExecuteReader: Connection property has not been initialized.
Does anyone know what is going wrong or a simple way to do this?
You can use this for your problem :). :
CREATE PROCEDURE dbo.SearchAllDatabases
#SearchTerm NVARCHAR(255) = NULL
AS
BEGIN
SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
IF #SearchTerm IS NULL OR #SearchTerm NOT LIKE N'%[^%^_]%'
BEGIN
RAISERROR(N'Please enter a valid search term.', 11, 1);
RETURN;
END
CREATE TABLE #results
(
[database] SYSNAME,
[schema] SYSNAME,
[table] SYSNAME,
[column] SYSNAME,
ExampleValue NVARCHAR(1000)
);
DECLARE
#DatabaseCommands NVARCHAR(MAX) = N'',
#ColumnCommands NVARCHAR(MAX) = N'';
SELECT #DatabaseCommands = #DatabaseCommands + N'
EXEC ' + QUOTENAME(name) + '.sys.sp_executesql
#ColumnCommands, N''#SearchTerm NVARCHAR(MAX)'', #SearchTerm;'
FROM sys.databases
WHERE database_id > 4 -- non-system databases
AND[state] = 0-- online
AND user_access = 0; -- multi-user
SET #ColumnCommands = N'DECLARE #q NCHAR(1),
#SearchCommands NVARCHAR(MAX);
SELECT #q = NCHAR(39),
#SearchCommands = N''DECLARE #VSearchTerm VARCHAR(255) = #SearchTerm;'';
SELECT #SearchCommands = #SearchCommands + CHAR(10) + N''
SELECT TOP(1)
[db] = DB_NAME(),
[schema] = N'' + #q + s.name + #q + '',
[table] = N'' + #q + t.name + #q + '',
[column] = N'' + #q + c.name + #q + '',
ExampleValue = LEFT('' + QUOTENAME(c.name) + '', 1000)
FROM '' + QUOTENAME(s.name) + ''.'' + QUOTENAME(t.name) + ''
WHERE '' + QUOTENAME(c.name) + N'' LIKE #'' + CASE
WHEN c.system_type_id IN(35, 167, 175) THEN ''V''
ELSE '''' END + ''SearchTerm;''
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.columns AS c
ON t.[object_id] = c.[object_id]
WHERE c.system_type_id IN (35, 99, 167, 175, 231, 239)
AND c.max_length >= LEN(#SearchTerm);
PRINT #SearchCommands;
EXEC sys.sp_executesql #SearchCommands,
N''#SearchTerm NVARCHAR(255)'', #SearchTerm;';
INSERT #Results
(
[database],
[schema],
[table],
[column],
ExampleValue
)
EXEC[master].sys.sp_executesql #DatabaseCommands,
N'#ColumnCommands NVARCHAR(MAX), #SearchTerm NVARCHAR(255)',
#ColumnCommands, #SearchTerm;
SELECT[Searched for] = #SearchTerm;
SELECT[database],[schema],[table],[column],ExampleValue
FROM #Results
ORDER BY[database],[schema],[table],[column];
END
GO
And use it like this :
exec SearchAllDatabases #SearchTerm = '%value%'
Or execute this stored procedure from your code.
using (SqlConnection connection = new SqlConnection(#"data source="SERVER NAME";integrated security=false;uid="USER";password="PASSWORD";"))
{
conn.Open();
// 1. create a command object identifying the stored procedure
SqlCommand cmd = new SqlCommand("SearchAllDatabases", conn);
// 2. set the command object so it knows to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which will be passed to the stored procedure
cmd.Parameters.Add(new SqlParameter("#SearchTerm", value));
cmd.ExecuteNonQuery();
}
Your code
SqlCommand columncommand = new SqlCommand(string.Format(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection));
The end of the statement has )), putting table connection as a parameter for string.Format, which you dont use, so either, move it or...
You should have:
SqlCommand columncommand = new SqlCommand(#"SELECT * FROM INFORMATION_SCHEMA.COLUMNS where TABLE_Name=" + tables, tableconnection);
I'm getting following error:
Insert Error: Column name or number of supplied values does not match
table definition.
Total column in excel is = 17
Total field in table = 17 + 3 = 20
among 3 fiedls 1 is (primarykeyid-autogenerate) 2 is (will get from another textbox) and 3 is (defaulvalue 1)
i don't know how to pass text box value and default value to procedure.
Please suggest me a way
Here is my stored procedure code
USE [Demo]
GO
/****** Object: StoredProcedure [dbo].[spx_ImportFromExcel07] Script Date: 03/21/2014 18:25:49 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spx_ImportFromExcel07]
#SheetName varchar(20),
#FilePath varchar(300),
#HDR varchar(3),
#TableName varchar(50)
AS
BEGIN
DECLARE #SQL nvarchar(1000)
IF OBJECT_ID (#TableName,'U') IS NOT NULL
SET #SQL = 'INSERT INTO ' + #TableName + ' SELECT * FROM OPENDATASOURCE'
ELSE
SET #SQL = 'SELECT * INTO ' + #TableName + ' FROM OPENDATASOURCE'
SET #SQL = #SQL + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL = #SQL + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL = #SQL + #HDR + ''''''')...['
SET #SQL = #SQL + #SheetName + ']'
EXEC sp_executesql #SQL
END
and here is my insertion code:
protected void btnSave_Click(object sender, EventArgs e)
{
string FileName = lblFileName.Text;
string Extension = Path.GetExtension(FileName);
string FolderPath = Server.MapPath(ConfigurationManager.AppSettings["FolderPath"]);
string CommandText = "";
switch (Extension)
{
case ".xls": //Excel 97-03
CommandText = "spx_ImportFromExcel03";
break;
case ".xlsx": //Excel 07
CommandText = "spx_ImportFromExcel07";
break;
}
//insertDB();
String strConnString = ConfigurationManager.ConnectionStrings["CARGONETConnectionString"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = CommandText;
cmd.Parameters.Add("#SheetName", SqlDbType.VarChar).Value = ddlSheets.SelectedItem.Text;
cmd.Parameters.Add("#FilePath", SqlDbType.VarChar).Value = FolderPath + FileName;
cmd.Parameters.Add("#HDR", SqlDbType.VarChar).Value = rbHDR.SelectedItem.Text;
cmd.Parameters.Add("#TableName", SqlDbType.VarChar).Value = "TB_TransAgentSeaFreightRate";
cmd.Connection = con;
try
{
con.Open();
object count = cmd.ExecuteNonQuery();
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = count.ToString() + " records inserted.";
}
catch (Exception ex)
{
lblMessage.ForeColor = System.Drawing.Color.White;
lblMessage.Text = ex.Message;
}
finally
{
con.Close();
con.Dispose();
Panel1.Visible = true;
//Panel2.Visible = false;
dg_AgentSFR.Visible = true;
}
}
Please Help me..
I dont know how to pass textbox value and defaulvalue to storedprocedure.
Thanks in advance
First, I recommend you get rid of the dynamic SQL in your stored procedure. Dynamic SQL will leave you vulnerable to SQL injection. "lblFileName.Text" is the most likely place that I see in the provided code for the injection to occur, but with the way the stored procedure is written, you are vulnerable with every parameter. You should parse the values to the correct types before you call the stored procedure. The parameters in the stored procedure should be the type of the columns in the table respectively. As for the table selection you are making, ask yourself how often this will change?
If it is not practical to write inserts for each table due to a large number of tables, then you need to check the stored procedure's parameters for SQL injection.
If you need a default value, you can easily put it on the stored procedure. Then you can do a check and skip the parameter in the code behind.
Stored Procedure:
CREATE PROCEDURE spExample
#nExample int = 1
AS
Code Behind:
int value
if(int.TryParse(TextBox1.Text, out value))
{
// add parameter here.
}
http://technet.microsoft.com/en-us/library/ms189330(v=sql.105).aspx
http://en.wikipedia.org/wiki/SQL_injection
I have the following Stored Procedure :
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result nvarchar(500) -- this one should return string.
DECLARE #variable1 NVARCHAR(50)
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from dbo.Table2))
DECLARE #variable2 NVARCHAR(50)
update dbo.Table1 set columnX = 1 where column1 not in (select column1 from dbo.Table2)
set #variable2 = ##ROWCOUNT
and so on... it continues like 200 rows of script with at least 10-12 variables
after that I want to get result like this
'Hello,' +
'Some Text here' +
#date +': ' +
'Explaining text for variable1- ' + #variable1 +
'Updated rows from variable2 - ' + #variable2 +
'some other select count - ' + #variable3 +
'some other update rowcount - '+ #variable4
......
till now i was able to get this with PRINT Statement, but can't take it to variable in my C# code which goes like this:
public void Execute_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Are you sure you want to execute the program?", "Confirm Start", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.No)
{
string connectionString = GetConnectionString(usernamePicker.Text, passwordPicker.Text);
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("dbo.ProcedureName", connection))
{
connection.Open();
cmd.CommandText = "dbo.ProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#date", SqlDbType.VarChar).Value = dateTimePicker1.Text;
SqlParameter result = cmd.Parameters.Add("#result", SqlDbType.VarChar);
result.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteScalar();
var resultout = (string)cmd.Parameters["#result"].Value;
connection.Close();
TextMessage.Text = dateTimePicker1.Text;
}
}
}
}
all i get for result is 0 or NULL or etc.
i tried to return value from SQL with PRINT, RETURN, SET, OUTPUT ....... but nothing seems to work. However fetching variable from C# to SQL seems like child-work. Any ideas?
If you want to return the concatenate string as output then at the end of the procedure just write select #result. Make sure that you have concatenated it before this statement.
This will return you the string which you can use in your c# code as a string.
Change your stored procedure to this:
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50),
#variable1 NVARCHAR(50) output,
#variable2 NVARCHAR(50) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #result nvarchar(500) -- this one should return string.
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from dbo.Table2))
update dbo.Table1 set columnX = 1 where column1 not in (select column1 from dbo.Table2)
set #variable2 = ##ROWCOUNT
and modify your code like this:
SqlParameter result1 = cmd.Parameters.Add("#variable1", SqlDbType.VarChar);
result1.Direction = ParameterDirection.ReturnValue;
SqlParameter result2 = cmd.Parameters.Add("#variable2", SqlDbType.VarChar);
result2.Direction = ParameterDirection.ReturnValue;
ok lets say I did this procedure
ALTER PROCEDURE [dbo].[ProcedureName]
#date NVARCHAR(50),
#result nvarchar(500) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #variable1 NVARCHAR(50)
set #variable1 = (SELECT COUNT(*) FROM dbo.Table1 WHERE column1 not in (select column1 from Table2))
set #result = #variable1 + ' some text '
i want "#result" to be output text from procedure and get it with C#
I have a method which includes sql statement . it is
public Boolean addRSS(string RSS_title, string Description, DateTime datetime, string RSS_Link, string user_name, float rate)
{
// Console.WriteLine(MyString.Remove(5, 10));
// string a = date.ToString().Replace('.', '-');
Boolean res = false;
string sql = "INSERT INTO My_RSS ( RSS_Title,RSS_Description,RSS_Date,RSS_Link,RSS_Rate,UserName) values('"
+
RSS_title + "','" +
"FFFFFFFFFFFFFFFFFFFFFFFFFAAASDASDASDASD" +
"', SYSUTCDATETIME(),'" +
RSS_Link + "'," +
rate + ",'"+
user_name +
"')";
try
{
// hasan = hasan.Insert(c, hasan);
SqlCommand cmd = new SqlCommand(sql, Connect());
cmd.ExecuteNonQuery();
res = true;
}
catch (Exception)
{
res = false;
}
return res;
}
It gives the error when I try to enter this input http://rss.feedsportal.com/c/32727/f/510887/s/1da50441/l/0Lekonomi0Bmilliyet0N0Btr0Cenflasyon0Eyuzde0E50Ee0Einene0Ekadar0Esikacak0E0Cekonomi0Cekonomidetay0C210B0A30B20A120C15181930Cdefault0Bhtm/story01.htm to "link column" and
it gives error which is
Incorrect syntax near 'e'.
The identifier that starts with 'Lekonomi0Bmilliyet0N0Btr0Cenflasyon0Eyuzde0E50Ee0Einene0Ekadar0Esikacak0E0Cekonomi0Cekonomidetay0C210B0A30B20A120C15181930Cdefau' is too long. Maximum length is 128.
Unclosed quotation mark after the character string ')'.
Also,In the sql side this colum is varchar(455)
The error is saying that the identifier name is too long; this combined with the unclosed quotation mark error means you probably missed an opening quote. That is, you have this:
INSERT INTO Foo ( A ) VALUES ( AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
instead of
INSERT INTO Foo ( A ) VALUES ( 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
You shouldn't be building your queries via string concatentation; this is one of the reasons. Parameterized queries will get the quoting right for you. (Note: you don't need to be using stored procs to use parameterized queries.)
var sql = "INSERT INTO My_RSS ( Title, Description, Date, Link, Rate, Name )
VALUES ( #Title, #Desc, #PostDate, #Link, #Rate, #Name )";
SqlCommand cmd = new SqlCommand(sql, Connect());
cmd.Parameters.Add("#Title", SqlDbType.VarChar, 100).Value = RSS_title;
cmd.Parameters.Add("#Desc", SqlDbType.VarChar, 8192).Value = RSS_description;
cmd.Parameters.Add("#PostDate", SqlDbType.SmallDateTime).Value = DateTime.Now;
cmd.Parameters.Add("#Rate", SqlDbType.Int).Value = rate;
etc.
You Can also add SET QUOTED_IDENTIFIER OFF before 'sql' string and SET QUOTED_IDENTIFIER On after 'sql'
QUOTED IDENTIFIER ON/OFF:
This specifies the setting for usage of double quotation. IF this is on, double quotation mark is used as part of the SQL Server identifier (object name). This can be useful in situations in which identifiers are also SQL Server reserved words.
sql = "SET QUOTED_IDENTIFIER OFF " + sql + " SET QUOTED_IDENTIFIER OFF ";
SqlCommand cmd = new SqlCommand(sql, Connect());
cmd.ExecuteNonQuery();
res = true;
You should use this in this case.