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!
Related
I have a DB which is connected like this.
I am writing a WPF app to do simple insert/delete/update stuff to tables.
The problem goes like this:
I get an Advertisement object and try to insert it into the DB
public static int Insert(Advertisement Advertisement)
{
Database db = new Database();
db.Connect();
SqlCommand command = db.CreateCommand(SQL_INSERT);
PrepareCommand(command, Advertisement);
int ret = db.ExecuteNonQuery(command);
db.Close();
return ret;
}
The SQL_INSERT
public static String SQL_INSERT = "INSERT INTO \"Advertisement\" VALUES (#IDProduct," +
" #CampaignDescription, #CampaignStart, #CampaignEnd)";
IDAdvertisement is an IDENTITY.
I have a trigger set on Advertisement table INSERT
ALTER trigger [dbo].[AutomaticUserAdvertisementScoreCalculating]
ON [dbo].[Advertisement]
AFTER INSERT
AS
begin
begin transaction;
declare Users cursor for
Select "User".IDUser, Sum(Price), inserted.IDProduct from "User"
join Purchase as pu on "User".IDUser = pu.IDUser
join PurchaseProduct as pp on pu.IDPurchase = pp.IDPurchase
join Product as pr on pp.IDProduct = pr.IDProduct
join inserted on pr.IDProduct = inserted.IDProduct
where pr.ProductType = (select ProductType from Product
join Advertisement on Product.IDProduct = Advertisement.IDProduct
join inserted on Advertisement.IDProduct = inserted.IDProduct
where Advertisement.IDAdvertisement = inserted.IDAdvertisement)
GROUP BY "User".IDUser, inserted.IDProduct
HAVING Sum(Price) > 50;
declare #IDUser int;
declare #Price decimal;
declare #IDProduct int;
open Users;
fetch next from Users into #IDUser,#Price, #IDProduct;
while ##FETCH_STATUS=0
begin
insert into UserAdvertisementScore values(#IDUser, (select IDAdvertisement from Advertisement where IDProduct = #IDProduct), #Price);
fetch next from Users into #IDUser, #Price, #IDProduct;
end
close Users;
deallocate Users;
commit;
end
I don't know why, but depending on the IDProduct used, it might throw out this error.
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
Please tell me if you need any more information on this
I didn't feel that was really a duplicate. Sure the error was the same thing but the real issue in this question was that the trigger was majorly flawed. Pretty sure your entire trigger body could simplified to something pretty close to this. And you should NOT use transactions inside a trigger. There is already a transaction in progress and anything you do will cause the original transaction to get out of whack.
insert UserAdvertisementScore
( --or whatever the column names are. You should ALWAYS specify the columns for an insert
[User]
, Price
, IDProduct
)
Select u.IDUser
, Sum(Price)
, i.IDProduct
from [User] u
join Purchase as pu on u.IDUser = pu.IDUser
join PurchaseProduct as pp on pu.IDPurchase = pp.IDPurchase
join inserted i on pr.IDProduct = i.IDProduct
join Product as pr on pp.IDProduct = pr.IDProduct
GROUP BY u.IDUser
, i.IDProduct
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 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'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.
I want to get the count of rows of a table.
cmd.CommandText = "SELECT COUNT(*) FROM (SELECT * FROM (SELECT * FROM EMPLOYEE ))";
Records = int.Parse(cmd.ExecuteScalar().ToString());
even if there is 1 row in employee table, Records always have value 0.
why ExecuteScalar() returns 0?
What you are trying to calculate is the number of rows in the EMPLOYEE table, therefore Pranav and Vinod are right. But assuming you try to simplify your situation just to point directly to your problem, I would say that you need to give names to your temporary tables like this:
cmd.CommandText = "SELECT COUNT(*) FROM (SELECT * FROM (SELECT * FROM EMPLOYEE ) as T1) as T2";
Records = int.Parse(cmd.ExecuteScalar().ToString());
That should do the trick.
One additional suggestion is not to use count(0); instead use count(0). '*' brings all data in the view; which is an unnecessary performance decrement for count function.
It returns 0 because your SQL request isn't valid.
You should always try your requests directly against your database (for instance using SQL Server Management Studio if you are using SQL Server) before writing them in your code. You would have seen it doesn't return anything because it has a syntax error.
If you want to use nested SELECT * FROM as you wrote, here's the valid SQL request that will return what you expected:
SELECT COUNT(*) FROM (SELECT * FROM (SELECT * FROM EMPLOYEE ) AS Foo1 ) AS Foo2
In any case, as all other answers have noted, this doesn't make much sense, and must be replaced by:
SELECT COUNT(*) FROM EMPLOYEE
Try this:
cmd.CommandText = "SELECT COUNT(*) FROM EMPLOYEE";
int Records = (int)cmd.ExecuteScalar();
That should return the number of rows in the EMPLOYEE table.
To double check, use the SQL management studio to execute the same code against your SQL server and see what the result is. Is it possible that your application is configured to point a different database to the one that you are viewing?
Just say:
cmd.CommandText = "SELECT COUNT(*) FROM EMPLOYEE";
Records = int.Parse(cmd.ExecuteScalar().ToString());
Try this:
cmd.CommandText = "SELECT COUNT(*) FROM EMPLOYEE"
Int record=(Int32)cmd.Executescalar();