I'm using MySQL with Visual Studio 2010 C# language.
I need to make a query.
SELECT a field, if this field is null or equals to 0
Make another SELECT and if it is different <> from null or 0.
Make another SELECT.
I also tried to follow the suggestion that appears when you write the title above, but nothing.
Something Like:
SELECT cart.cod_dependent (if cart.cod_dependent <> 0, Select ass.matricula, ass.nome, ass.situacao_social, ass.categoria, ELSE IF cart.cod_dependent = null Make another select)
Each select will be in different Tables, but all in the same database.
------ UPDATE 10/08/2012 09:59 --------
Now I'm Trying what you said Radu Bompa, but it says "fatal error encoutering during the Execution command" =\ .
MySqlCommand cmd = new MySqlCommand();
string sql = #"SELECT #cod_dep = cart.cod_dependente FROM carteiras as cart
IF #cod_dep IS NULL
BEGIN
SELECT ass.matricula, ass.nome, ass.situacao_social, ass.categoria FROM associados AS ass INNER JOIN categorias AS cat ON cat.codigo = ass.categoria,
INNER JOIN situacoes_social AS ss ON ass.situacao_social = ss.codigo
END
ELSE
BEGIN
SELECT dep.nome, dep.matricula, dep.situacao_social, ss.descricao FROM dependentes INNER JOIN situacao_social as ss dep.situacao_social = ss.codigo
END
WHERE cart.numero = #carteira";
cmd.CommandText = sql;
cmd.CommandType = CommandType.Text;
string dependente = "";
cmd.Parameters.Add(new MySqlParameter("#carteira", MySqlDbType.Int32)).Value = carteira;
DataSet ds = _dal.Consultar(cmd);
Maybe something like this could work:
SELECT #SomeValue = cart.cod_dependent FROM cart
--#SomeValue is a variable, declared for this purpose
IF #SomeValue IS NULL
BEGIN
SELECT ass.matricula, ass.nome, ass.situacao_social, ass.categoria FROM table2
END
ELSE
BEGIN
SELECT field FROM table3
END
You could also try to use a stored procedure.
Related
I am trying to use a two line query to a mysql database like this with C#:
set #var = 1; select id from table where id = #var`;
Executing this in C# does not give any error, the reader has columns, but don't have rows in it, so, no data is retrieved.
Running the same queries in the workbench retrieve the expected data.
Running one query to calculate the variable and other to use it replaced works.
I want to use a variable to store references and use it to filter queries that provide an union.
SET #my_value = (select min(id) from (select id from datatable limit 2000) as a);
and a complex select query, that i can resume in:
select * from
datatable as a
left join (
(select databalt2 where id > #my_value) as ba union
(select datatable3 where id > #my_value) as bb) as b
on a.id = b.id
where a.id > #my_value;
The datareader should obtain the results, but instead reports that it has no rows, but has the correct amount of columns.
And, obviously, shows no results, where it should.
Edit 1: C# code
string query = #"
SET #`my_value` = (select min(id) from (select id from datatable limit 2000) as a);
select * from
datatable as a
left join (
(select databalt2 where id > #`my_value`) as ba union
(select datatable3 where id > #`my_value`) as bb) as b
on a.id = b.id
where a.id > #`my_value`;
";
try
{
MySqlCommand command = Connection.CreateCommand();
MySqlDataReader reader;
command.CommandTimeout = commandTimeout;
command.CommandText = query;
reader = command.ExecuteReader();
}
catch (Exception ex)
{
}
These queries using local variables are possible, the local variable has to be inside like #`var`, because it can be identifyied as a local parameter.
I was missing a in a local variable call. So ... a problem between the screen and the chair!
I need to do a full outer join on 2 datatables dinamically, I don't know what columns are in the datatables but they will be the same in each table, I also only have the name of the column I need to do the join on in a variable. Is there a way of doing this?
What I need to do is join 2 datatables in a C# script. I'm using a Dataflow in an SSIS to get data from a couple of files, and at the end I need to compare the 2 final sets of data. I need to to this on whatever 2 datatables as long as they have the same columns, so I can't finish the process in an SSIS as I need to specify the columns.
The GetData() I just use it in case I need to compare 2 tables but donnesPROD and donnesDEV are filled from object variables in the SSIS.
Here's my code so far :
DataTable donnesPROD = GetData(connectionPROD, sql_request);
DataTable donnesDEV = GetData(connectionDEV, sql_request);
Here's the code for GetData :
DataTable GetData(string cs, string query)
{
OleDbConnection conn = new OleDbConnection(cs);
conn.Open();
OleDbCommand cmd = new OleDbCommand(query, conn);
DataTable dt = new DataTable();
dt.Load(cmd.ExecuteReader());
conn.Close();
return dt;
}
I have the list of the columns in another datatable, and I have the name of the primary key in a string variable key. From here I need to be able to do a fullouterjoin of donnesPROD and donnesDEV on key. Can this be done this way? Or is there a way of generating the script code it self dynamically and then execute it?
You have two options.
Conditional joins
If you don't know the specific column name, but you do have some idea what the column name might be, you could do a conditional join like this:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
SELECT *
FROM TableA
JOIN TableB ON (#JoinColumn = 'ColumnA' AND TableA.ColumnA = TableB.ColumnA)
OR (#JoinColumn = 'ColumnB' AND TableA.ColumnB = TableB.ColumnB)
OR (#JoinColumn = 'ColumnC' AND TableA.ColumnC = TableB.ColumnC)
END
You may not get the best performance out of this (the conditional joins will confuse the query engine and it may not pick the best index, if it picks one at all). If the table is very large you could also do something like this. It is a bit painful-looking but will get better performance:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
IF (#JoinColumn = 'ColumnA') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnA = TableB.ColumnA
END
IF (#JoinColumn = 'ColumnB') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnB = TableB.ColumnB
END
IF (#JoinColumn = 'ColumnC') BEGIN
SELECT *
FROM TableA
JOIN TableB ON TableA.ColumnC = TableB.ColumnC
END
END
If TableA or TableA are part of a larger query, and you'd end up duplicating tons of SQL, you could always extract the resultset for just TableA and TableB into a temporary table, then use the temporary table in the larger query.
Dynamic SQL
If you don't have the foggiest about the column name and there are tons of possibilities, you could construct the SQL as a string and join that way. You should validate the column name that is passed in; not only will that make sure the column actually exists, but it will prevent the dynamic SQL from being constructed when #JoinColumn contains an injection attack, since legal column names do not contain SQL statements. Example:
CREATE PROCEDURE ExampleDynamicJoin(#JoinColumn AS VarChar(40))
AS
BEGIN
DECLARE #Sql AS VarChar(MAX)
IF NOT EXISTS
(
SELECT 0
FROM syscolumns c
JOIN sysobjects o ON o.id = c.id
WHERE o.Name = 'TableA'
AND c.Name = #JoinColumn
)
RAISERROR (15600,-1,-1, 'ExampleDynamicJoin'); //Throw error if column doesn't exist
SET #Sql =
'SELECT *
FROM TableA
JOIN TableB ON TableA.' + #JoinColumn + ' = TableB.' + #JoinColumn
sp_ExecuteSql #Sql
END
Or, if you don't use stored procedures,
DataTable ExampleDynamicJoin(string joinColumn)
{
if (!ValidateColumn(joinColumn)) throw new ArgumentException();
var sql = String.Format(
#"SELECT *
FROM TableA
JOIN TableB ON TableA.{0} = TableB.{0}",
joinColumn
);
using (var connection = GetConnectionFromSomewhere())
{
using (var cmd = new SqlCommand
{
CommandText = sql,
CommandType = CommandType.Text,
Connection = connection
})
{
var reader = cmd.ExecuteReader();
var table = new DataTable();
table.Load(reader);
return table;
}
}
}
When using dynamic SQL you should always use parameters if possible. But you can't use parameters as a column name, so in this case you have to concatenate. When concatenating, ALWAYS white list the inputs. That is why I included a function named ValidateColumn which could look like this:
bool ValidateColumn(string columnName)
{
switch columnName.ToUpper()
{
case "COLUMNA":
case "COLUMNB":
case "COLUMNC":
return true;
default:
return false;
}
}
I'm trying to make some common code for retrieving identities from tables and that involves making an unsafe query string to inject the table name.
I read everywhere that I cannot safely inject the table name. So I want to query if the table exists, then based on the result, perform a real or dummy query.
var unsafeTableQuery = "SELECT [Id] FROM [dbo].[" + tableName + "] WHERE [BulkInsertSessionID] = #bulkInsertSessionId";
var guardQuery =
"DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );" +
"IF (#Exists = 0) SELECT TOP 0 NULL 'Id'" +
"ELSE " + unsafeTableQuery;
var cmd = new SqlCommand(guardQuery, conn, tran);
cmd.Parameters.Add(new SqlParameter("#TableName", tableName));
cmd.Parameters.Add(new SqlParameter("#bulkInsertSessionId", bulkInsertSessionId));
using (SqlDataReader reader = cmd.ExecuteReader())
{
int index = 0;
while (reader.Read())
{
int id = (int)reader[0];
entities[index++].Id = id;
}
}
Even though I have an unsafe concatenation, I'm first querying the table name against the sys.tables by a parameter. And if it doesn't exist, the IF..ELSE block will never step into the unsafe query.
For easier readability I'm expecting to run the following query:
DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );
IF(#Exists = 0)
SELECT TOP 0 NULL 'Id'
ELSE
SELECT [Id] from <InjectedTableName> where BulkInsertSessionID = #bulkSessionId
Am I correct in my assumption that this is safe?
Suppose your users have an access to change the variable tableName. I suppose some user types it on some form. Suppose he types this:
Users]; DROP TABLE Users;--
Then your whole command will be:
DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );
IF(#Exists = 0)
SELECT TOP 0 NULL 'Id'
ELSE
SELECT [Id] from [Users]; DROP TABLE Users;-- where BulkInsertSessionID = #bulkSessionId
This will do its IF ELSE part and then will go to next statement which is:
DROP TABLE Users;
Note that drop statement will execute in any case even if ELSE part is not executed, because you don't have BEGIN END. Note that the rest is commented out... This is most basic injection method...
i made a simple query joining two tables in the database using inner join. the query is given as follows:
Select t1.UserName,t1.Title,t1.FirstName,t1.LastName,t1.MiddleName,t1.IsActive,t1.ProgramID,t2.Email
from table1 t1
inner join table2 t2 on t1.UserId = t2.UserId
the query executes well in SQL Server Management Studio and returns rows as needed but while debugging my code in Visual Studio, when it reaches at
adapter.fill(dataset);
it throws the following exception:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
here is the C# code snippet:
string selectCmd = #"Select t1.UserName,t1.Title,t1.FirstName,t1.LastName,t1.MiddleName,t1.IsActive,t1.ProgramID,t2.Email
from table1 t1
inner join table2 t2 on t1.UserId = t2.UserId ";
DataSet dataset = new DataSet();
using (SqlConnection conn = new SqlConnection(MyConnString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(selectCmd, conn);
conn.Open();
adapter.Fill(dataset);
}
Any suggestions please?? Any help would be greatly appreciated.
Your join returning more than one value and you're trying to put these values in a single parameter..
Example: ----It's your error query
DECLARE #Test INT
SET #Test = (SELECT ID FROM ABC A INNER JOIN XYZ X ON A.ID = X.AID)
Solution:
DECLARE #Test INT
SET #Test = (SELECT TOP 1 ID FROM ABC A INNER JOIN XYZ X ON A.ID = X.AID)
ok guys it was a timer job issue. one has to restart the sharepoint timer service before deploying the solution.
I am using asp.net, .NET 3.5, C#, and SQL Server Express 2005.
I have created a stored procedure in SQL, and when I run SP from SQL server it takes less than 1 second to return results. I have also tried that query in query analyzer and it also gives me results in less than 1 second. But when I try to call this SP from .NET (C#), it takes a long time, and then gives a timeout error.
Here is the code I am using to call the stored procedure:
SqlConnection con = new SqlConnection();
con.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
con.Open();
SqlCommand command = new SqlCommand("spReport_SiteUsage_KP", con);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("#fromDate", SqlDbType.DateTime));
command.Parameters.Add(new SqlParameter("#toDate", SqlDbType.DateTime));
command.Parameters[0].Value = Convert.ToDateTime(DatePicker1.SelectedDate.ToShortDateString());
command.Parameters[1].Value = DatePicker2.SelectedDate;
int i = command.ExecuteNonQuery();
con.Close();
Store Procedure :
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spReport_SiteUsage_KP]
#fromDate datetime = null,
#toDate datetime = null
AS
truncate table dbo.RPT_SiteUsage
IF (#FromDate is not null and #ToDate is not null) --Hourly Report, grouped by hour
Begin
insert into RPT_SiteUsage
select '' as ReportType,
'Site Usage for '+ datename(mm,#fromDate)+' '+datename(dd,#fromDate)+', '+datename(yy,#fromDate) +
' To '+datename(mm,#toDate)+' '+datename(dd,#toDate)+', '+datename(yy,#toDate) as ReportTitle,
min(#fromDate) as FromDate,max(#toDate) as ToDate,
isnull(count(s.SessionId),0) VisitsTotal,
isnull(count(distinct(s.cookieid)),0) VisitsUnique,
isnull(sum(PagesVisited),0) PageViews,
isnull(round(avg(convert(decimal(10,2),PagesVisited)),2),0) PagePerVisit,
isnull(min(PagesVisited),0) MinNoPageViews,
isnull(max(PagesVisited),0) MaxNoPageViews,
isnull(round(avg(convert(decimal(10,2),TimeInSiteMinutes)),2),0) AvgTimeInSite,
isnull(min(TimeInSiteMinutes),0) MinTimeSpent,
isnull(max(TimeInSiteMinutes),0) MaxTimeSpent,
isnull(sum(NewPeople),0) as NewVisitors
from
dbo.UMM_UserAction ua inner join dbo.UMM_Session s on ua.SessionId=s.Sessionid
left join
(select ua.sessionId, datediff(ss,min(Actiondate),max(Actiondate))/60 TimeInSiteMinutes
from dbo.UMM_UserAction ua
where ActionDate between #fromDate and #toDate
group by ua.sessionid
) sessionTime on ua.sessionId = sessionTime.sessionid
left join
(select ua.sessionId, 0 as NewPeople
from dbo.UMM_UserAction ua
inner join dbo.UMM_Session s on ua.SessionId=s.SessionId
inner join dbo.UMM_Cookie c on s.CookieId=c.CookieId
where ua.actiondate< #fromDate --this is the from date
group by UserId,ua.sessionId
) Old on ua.sessionId = Old.sessionid
left join
(select ua.sessionId,count(distinct(uaP.PageEntryId)) as PagesVisited
from dbo.UMM_UserAction ua,
dbo.UMM_UserActionPageReview uaP
where ua.UserActionId=uaP.UserActionId
and ActionDate between #fromDate and #toDate
group by ua.sessionId
)pVisited on ua.sessionId = pVisited.sessionId
where ActionDate between #fromDate and #toDate
IF (select count(*) from RPT_SiteUsage)=0
insert into RPT_SiteUsage
select '(1 day)' as ReportType,
'Site Usage for '+datename(mm,#fromDate)+' '+datename(dd,#fromDate)+', '+datename(yy,#fromDate) +
' To '+datename(mm,#toDate)+' '+datename(dd,#toDate)+', '+datename(yy,#toDate) as ReportTitle,
min(#fromDate) as FromDate,max(#toDate) as ToDate,
0 as VisitsTotal,
0 as VisitsUnique,
0 as PageViews,
0 as PagePerVisit,
0 as MinNoPageViews,
0 as MaxNoPageViews,
0 as AvgTimeInSite,
0 as MinTimeSpent,
0 as MaxTimeSpent,
0 as NewVisitors
END
Another idea, the TimeOut of each SqlCommand is also controlled individually, so, you can control it with CommandTimeOut property.
command.CommandTimeout = 120;
However, I would check the execution plan to see where is it wasting or hogging db resources, I suggest this just for experiment, not on production.
Well - I would say there's an error in your connection string. Please check it.
If it takes long before the query returns an error, there is probably something wrong with your connection (string).
It could be the fun issue with a bad query plan cached on the proc. Especially if the guts of the proc just as a Query in Query Analyzer runs fine. Check this link out on how to resolve the situation: http://www.mssqltips.com/tip.asp?tip=1304