SQL Server Procedure Parameter List [duplicate] - sql

Say I have the a table with 3 columns : Id, Category, Name.
I would like to query the table that way :
Get me the rows for which
{ Category = "Cat1" AND Name = "ABC" } OR { Category = "Cat2" AND Name = "ABC" } OR { Category = "Cat2" AND Name = "DEF" }
How? Without having to resort to a huge list of WHERE OR
I was thinking of using IN...but is it possible to use that in conjunction with 2 columns?
Thanks!

You can create a temp table
create table #temp (Category varchar(50), Name varchar(50))
insert into #temp values ('Cat1', 'abc'), ('Cat2', 'cde'), ('Cat3', 'eee')
And then join your main table
select * from table1
inner join #temp
on table1.Category = #temp.Category and table1.Name = #temp.Name
If you want to use that approach from the code, you can do that using table parameters.
Define a table type:
CREATE TYPE dbo.ParamTable AS TABLE
( Category varchar(50), Name varchar(50) )
and a stored proc that will read the data:
create procedure GetData(#param dbo.ParamTable READONLY)
AS
select * from table1
inner join #param p
on table1.Category = p.Category and table1.Name = p.Name
Then you can use those from the C# code, for example:
using (var conn = new SqlConnection("Data Source=localhost;Initial Catalog=Test2;Integrated Security=True"))
{
conn.Open();
DataTable param = new DataTable();
param.Columns.Add(new DataColumn("Category", Type.GetType("System.String")));
param.Columns.Add(new DataColumn("Name", Type.GetType("System.String")));
param.Rows.Add(new object[] { "Cat1", "abc" });
using (var command = conn.CreateCommand())
{
command.CommandText = "GetData";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#param", param);
using (var reader = command.ExecuteReader())
{
// reading here
}
}
}

#Szymon's answer is the best, but if you absolutely need to do it in one query you can come up with a scheme to concatenate the two columns into one string and join candidate values using the same method. Then you can use IN instead of a bunch of ANDs and ORs.
SELECT *
FROM table
WHERE Category + ':' + Name IN ('Cat1:abc', 'Cat2:cde', 'Cat3:eee')
This has the distinct disadvantage of never being able to take advantage of indexes. But it's good for a quick and dirty solution.

With Sql2008 there is an interesting new clause VALUES in FROM:
select *
from mytable
inner join ( select * from (values('cat1', 'abc'),
'cat2', 'def') as T(cat,name) ) C
on mytable.category = c.cat and mytable.name = c.name

Create temporary table to store the key value pairs. Then query from your main table joinned with temporary table. Not as simple as adding IN(...), but this is the only way I can think and i believe IN(...) is not capable

Related

Access - Query not executable

The error is "The query must be based on at least one table or query".
The query:
INSERT INTO Gehaltsabrechnung (IBAN, MitarbeiterID, Betrag) VALUES (
(SELECT IBAN FROM Mitarbeiter WHERE MitarbeiterID = 2), 2,
(SELECT SUM(Stunden_Gearbeitet * Stundenlohn) FROM
(mitarbeiterrollen INNER JOIN ROLLE ON mitarbeiterrollen.RolleID = rolle.RolleID)
WHERE MitarbeiterID = 2)
)
Our "Gehaltsabrechnung" table
You want INSERT . . . SELECT. In MS Access, this would look like:
INSERT INTO Gehaltsabrechnung (IBAN, MitarbeiterID, Betrag)
SELECT m.IBAN, m.MitarbeiterID,
(SELECT SUM(Stunden_Gearbeitet * Stundenlohn)
FROM mitarbeiterrollen INNER JOIN
ROLLE
ON mitarbeiterrollen.RolleID = rolle.RolleID
WHERE MitarbeiterID = m.MitarbeiterID
)
FROM Mitarbeiter as m
WHERE m.MitarbeiterID = 2;
Notice that I replaced most of the 2s with references to m.MitarbeiterID. This helps ensure that typos won't affect the query.
I would also recommend using qualified column names in the subquery, but this version should work.
Our "MitarbeiterRollen" table: https://i.stack.imgur.com/7pDct.png
Our "Gehaltsabrechnung" table https://i.stack.imgur.com/dUKWd.png
Our "Rolle" table: https://i.stack.imgur.com/bhmYn.png
Our "Mitarbeiter" table: https://i.stack.imgur.com/yniNv.png

Sql Query with Temp tables in Visual Studio 2010 data grid

I apologize up front if this has been answered, i read several other posts and didn't see a clear answer to my question. I am a beginner at VS2010. Basically i have the below query and i want it to display in the data grid view when i run my program.
I can use VS2010 to join two actual tables but as you can see below the temp tables are very important.
IF OBJECT_ID('tempdb..#tempbatch') IS NOT NULL DROP TABLE #tempbatch
IF OBJECT_ID('tempdb..#tempbatch2') IS NOT NULL DROP TABLE #tempbatch2
IF OBJECT_ID('tempdb..#tempbatch1') IS NOT NULL DROP TABLE #tempbatch1
IF OBJECT_ID('tempdb..#tempbatch3') IS NOT NULL DROP TABLE #tempbatch3
IF OBJECT_ID('tempdb..#tempbatch4') IS NOT NULL DROP TABLE #tempbatch4
IF OBJECT_ID('tempdb..#tempbatch5') IS NOT NULL DROP TABLE #tempbatch5
IF OBJECT_ID('tempdb..#tempbatch6') IS NOT NULL DROP TABLE #tempbatch6
IF OBJECT_ID('tempdb..#tempbatch7') IS NOT NULL DROP TABLE #tempbatch7
IF OBJECT_ID('tempdb..#tempbatch8') IS NOT NULL DROP TABLE #tempbatch8
IF OBJECT_ID('tempdb..#tempbatch9') IS NOT NULL DROP TABLE #tempbatch9
IF OBJECT_ID('tempdb..#tempbatch10') IS NOT NULL DROP TABLE #tempbatch10
create table #tempbatch (rowid bigint primary key identity(1,1), shipmentno varchar(64))
insert into #tempbatch select * from #unitnames
select distinct b.dcsID, a.BoxType, b.BoxNO, b.shipmentno, b.PaletteWithinShipment into #tempbatch1 from #tempbatch c
join dva..Boxmapping as a
on c.shipmentno = a.shipmentno
join dva..Boxmapping as b
on a.boxno = b.BoxNO
--where b.shipmentno = '#rmn'
group by b.dcsID, a.BoxType, b.BoxNO, b.shipmentno, b.PaletteWithinShipment
order by b.PaletteWithinShipment, b.BoxNO
--select dcsid,boxtype,boxno,shipmentno from #tempbatch1
select distinct a.dcsid,b.dcsid as manifestDCS,b.rmn into #tempbatch3 from #tempbatch1 a
left outer join dva..manifestDCS b
on a.dcsid = b.dcsid
select distinct b.dcsid,a.rmn into #tempbatch5 from #tempbatch3 a
left outer join dva..manifestdcs b
on a.rmn = b.rmn
select b.dcsid as deliverexDCSID,a.dcsid,a.rmn,pbatch into #tempbatch4 from #tempbatch5 a
left outer join #tempbatch1 b
on a.dcsid = b.dcsid
join dva..document c
on a.dcsid = c.dcsid
where a.dcsid not in (select dcsid from dva..document where ftpstime is null) and a.dcsid not in (select dcsid from dva..boxmapping)
delete from #tempbatch4 where deliverexdcsid is not null
----- ******************************** START OF SECOND QUERY *********************************-------------
select * into #tempbatch6 from dva..Boxmapping
select distinct c.rmn,c.dcsid,b.dcsid as BoxDCSID,a.pbatch into #tempbatch8 from #tempbatch4 a
left outer join dva..manifestDCS b
on a.dcsid = b.dcsid
left outer join dva..manifestdcs c
on b.rmn = c.rmn
select distinct c.rmn,c.dcsid as Missing,a.dcsid,d.BoxNO,d.boxtype,e.palette,e.PaletteWithinShipment,e.shipmentno into #tempbatch9 from #tempbatch8 a
left outer join #tempbatch4 c
on a.rmn = c.rmn
left outer join dva..boxmapping d
on b.dcsid = d.dcsid
left outer join dva..boxmapping e
on d.boxno = e.boxno
delete from #tempbatch9 where dcsID is null
delete from #tempbatch9 where boxno is null
delete from #tempbatch9 where palette is null
select distinct rmn,missing,boxno,boxtype,PaletteWithinShipment,shipmentno from #tempbatch9
order by rmn,PaletteWithinShipment
Wrap the whole of your query in a stored procedure, i.e.
CREATE PROCEDURE dbo.MyData
AS
SET NOCOUNT ON;
BEGIN
<insert your SQL here>
END;
Back in Visual Studio you will need to open a connection to your database, then open a command that you will use in conjunction with a data reader. There should be plenty of examples of how to do this, but I will give you a very short sample (sorry it's in C#, I don't touch VB):
using (var con = new SqlConnection("Server=WHATEVERSERVER;Database=WHATEVERDBS;Trusted_Connection=True;"))
{
con.Open();
using (var com = con.CreateCommand())
{
com.CommantText = "EXECUTE <MyDatabase>.dbo.MyData;";
using (var dr = com.ExecuteReader())
{
while (dr.Read())
{
var row = new string[7];
row[0] = dr["rmn"].ToString();
row[1] = dr["missing"].ToString();
etc...
MyDataGrid.Rows.Add(row);
}
}
}
}
Finally, you can just pull back a row count from your data grid, to get the number of rows of data that you want to display in a window.
If you can't create a stored procedure then you could type the entire SQL script into the command text bit, but you would have to be very careful with the carriage returns, spacing, literals, quotes, etc.
Again, apologies that my example code is in C#, I was just wanting to give you a very basic framework, so at the very least you know what to go and type into Google...

How to query the database with a list of key-value pairs

Say I have the a table with 3 columns : Id, Category, Name.
I would like to query the table that way :
Get me the rows for which
{ Category = "Cat1" AND Name = "ABC" } OR { Category = "Cat2" AND Name = "ABC" } OR { Category = "Cat2" AND Name = "DEF" }
How? Without having to resort to a huge list of WHERE OR
I was thinking of using IN...but is it possible to use that in conjunction with 2 columns?
Thanks!
You can create a temp table
create table #temp (Category varchar(50), Name varchar(50))
insert into #temp values ('Cat1', 'abc'), ('Cat2', 'cde'), ('Cat3', 'eee')
And then join your main table
select * from table1
inner join #temp
on table1.Category = #temp.Category and table1.Name = #temp.Name
If you want to use that approach from the code, you can do that using table parameters.
Define a table type:
CREATE TYPE dbo.ParamTable AS TABLE
( Category varchar(50), Name varchar(50) )
and a stored proc that will read the data:
create procedure GetData(#param dbo.ParamTable READONLY)
AS
select * from table1
inner join #param p
on table1.Category = p.Category and table1.Name = p.Name
Then you can use those from the C# code, for example:
using (var conn = new SqlConnection("Data Source=localhost;Initial Catalog=Test2;Integrated Security=True"))
{
conn.Open();
DataTable param = new DataTable();
param.Columns.Add(new DataColumn("Category", Type.GetType("System.String")));
param.Columns.Add(new DataColumn("Name", Type.GetType("System.String")));
param.Rows.Add(new object[] { "Cat1", "abc" });
using (var command = conn.CreateCommand())
{
command.CommandText = "GetData";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#param", param);
using (var reader = command.ExecuteReader())
{
// reading here
}
}
}
#Szymon's answer is the best, but if you absolutely need to do it in one query you can come up with a scheme to concatenate the two columns into one string and join candidate values using the same method. Then you can use IN instead of a bunch of ANDs and ORs.
SELECT *
FROM table
WHERE Category + ':' + Name IN ('Cat1:abc', 'Cat2:cde', 'Cat3:eee')
This has the distinct disadvantage of never being able to take advantage of indexes. But it's good for a quick and dirty solution.
With Sql2008 there is an interesting new clause VALUES in FROM:
select *
from mytable
inner join ( select * from (values('cat1', 'abc'),
'cat2', 'def') as T(cat,name) ) C
on mytable.category = c.cat and mytable.name = c.name
Create temporary table to store the key value pairs. Then query from your main table joinned with temporary table. Not as simple as adding IN(...), but this is the only way I can think and i believe IN(...) is not capable

Linq Left Join returns repeated same rows for all set

my linq returns all repeated same rows for all set
run SQL in DB :
select top 20 * from t1
left join t2
on t1.sid= t2.sid
and t1.pid=t2.pid
where(t2.sid is null and t1.pid='r')
i can get 20 different rows of result.
then i write Linq:
Entities dbconn = new Entities();
List<t1> myResult = (
from t1Data in dbconn.t1
join t2Data in dbconn.t2
on new { sid = (int)t1.sid, pid= t1.pid}
equals new { sid= (int)t2.sid, pid= t2.pid}
into joinSet
from joinUnit in joinSet.DefaultIfEmpty()
where (joinUnit == null) && (t1.pid== "r")
select t1Data
).Take(20).ToList();
all rows of result are the some row.
select t1Data is wrong as t1Data is from the original dataset.
Instead, select the joined result: select joinSet.

Derived tables in Linq to SQL

I would like to implement this in Linq to SQL:
select * from (
select * from Orders) as A
Obviously this is a pointless example, but I just can't figure out how to do it!
Try something like this:
var subquery = from row in Orders select row;
var query = from row in subquery select row;
using (var dc = new NorthwindDataContext())
{
var A = from ordOuter in
from ordInner in dc.Orders
select ordInner
select ordOuter;
}