Select more columns with MAX function in SQLCE - c#

Need to find max value of id, and by this value I need to read value of others column. But it is influenced by another column type.
I used this sql command:
"SELECT * FROM Table WHERE id = (SELECT MAX(id) FROM Table WHERE type = 1)"
ID column is bigint type, and type is nchar. I tried use it with type = '1' too, but same problem.
Error is after "id = " section
Thanks for reply
EDIT:
SqlCeCommand com = new SqlCeCommand();
if (LocalType == '1') { com = new SqlCeCommand("SELECT req_id FROM Requisition WHERE id = (SELECT MAX(id) FROM Requisition WHERE type = 1)", con); }
else if (LocalType == '2') { com = new SqlCeCommand("SELECT req_id FROM Requisition WHERE id = (SELECT MAX(b.id) FROM Requisition AS b WHERE b.type <> 1)", con); }
using (com)
{
SqlCeDataReader reader = com.ExecuteReader();
}

The easiest way to do this is using top. If this is your real code, then you need to "escape" the word "table" because it is a reserved word:
select top 1 t.*
from [table] t
where type = '1'
order by id desc

Try naming the tables:
SELECT *
FROM Table AS a
WHERE id = (SELECT MAX(b.id) FROM Table AS b WHERE b.type = 1)

After a while on google, find that SQLCE in version 3.5 support SELECT TOP expression, but with difference with formating. It must be write with brackets
SELECT TOP(1) * FROM MyTable

Related

Check if exist each one row Separately and run the same code

I have two tables i want to check if exist Barcode from first Table to Second. But i want run the code only for the first row. When it will end then to run the same code for the second row and making the same for rest of my rows till it will end.
Here is an example of my code which i want to use: But How will i run the code for each row separately.Starting with first then with second,third and go on.
Code: For SQL
IF EXISTS ( SELECT Barcode FROM Table_1 where barcode = (select barcode from Table_2)
BEGIN
update Table_2 set Name = (select Name from Table_1)
END
ELSE
BEGIN
insert into Table_2 (Barcode,Name) (select Barcode,name from Table1)
END
Code: For C#
System.Data.SqlClient.SqlCommand CheckNone = new System.Data.SqlClient.SqlCommand("IF EXISTS( SELECT Barcode FROM Table_1 where barcode = (select barcode from Table_2) SELECT 1 ELSE SELECT 0", con);
con.Open();
var result = (int)CheckNone.ExecuteScalar();
if (result == 0)
{
SqlCommand cmd = new SqlCommand("insert into Table_2 (Barcode,Name) (select Barcode,name from Table1)",con);
cmd.ExecuteNonQuery();
con.Close();
}
else
{
SqlCommand cmd = new SqlCommand("update Table_2 set Name = (select Name from Table_1)",con);
cmd.ExecuteNonQuery();
con.Close();
}
}
It sounds like you just need to update the Name in Table 2 for rows with matching Barcode values in Table 1. You can to that for the entire table in teo queries:
UPDATE t2
SET Name = t1.Name
FROM Table2 t2
INNER JOIN Table1 t1
ON t2.Barcode = t1.Barcode
INSERT INTO Table2
(Barcode, Name)
SELECT Barcode, Name
FROM Table1
WHERE Barcode NOT IN
(SELECT Barcode FROM Table2)
If you really want to update one row at a time, then just add WHERE Barcode = #barcode to your SELECT queries and pass the paramater value to the Command in C#. Note however that it will be MUCH slower than doing it all at once.

How to i get result based on ids list passed as a varchar?

I am passing ids list as a varchar(500) and based upon that ids records are required.My sql code is
declare #Ids varchar(500) = '12964,12965,12966'
select *
from tblBooks
where BookID in (#Ids)
where BookID is varchar(50).Number of Ids can be 100.Converting #Ids into int gives following error
Conversion failed when converting the varchar value
'12964,12965,12966' to data type int
How do i find result as #Id are not converted into Int.
Use a table variable:
DECLARE #Ids TABLE (ID INT);
INSERT #Ids VALUES (12964),(12965),(12966);
SELECT *
FROM tblBooks
WHERE BookID in (SELECT ID FROM #Ids);
If you need to pass this to a procedure then you can use a table valued parameter:
CREATE TYPE dbo.ListOfInt AS TABLE (ID INT);
GO
CREATE PROCEDURE dbo.GetBooks #IDs dbo.ListOfInt READONLY
AS
BEGIN
SELECT *
FROM tblBooks
WHERE BookID in (SELECT ID FROM #Ids);
END
GO
DECLARE #IDs dbo.ListofInt;
INSERT #Ids VALUES (12964),(12965),(12966);
EXECUTE dbo.GetBooks #Ids;
Or From c#
var table = new DataTable();
table.Columns.Add("ID", typeof(int));
// ADD YOUR LIST TO THE TABLE
using (var connection = new SqlConnection("Connection String"))
using (var command = new SqlCommand("dbo.GetBooks", connection))
{
command.CommandType = CommandType.StoredProcedure;
var param = new SqlParameter("#Ids", SqlDbType.Structured);
param.TypeName = "dbo.ListofInt";
param.Value = table;
command.Parameters.Add(table);
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
// do something
}
}
}
Once the TYPE is in place, you don't even need to use a stored procedure. You can simply call a normal query:
using (var connection = new SqlConnection("Connection String"))
using (var command = new SqlCommand("SELECT * FROM tblBooks WHERE BookID IN (SELECT ID FROM #IDs)", connection))
{
var param = new SqlParameter("#Ids", SqlDbType.Structured);
param.TypeName = "dbo.ListofInt";
param.Value = table;
command.Parameters.Add(table);
connection.Open();
// ETC
}
Doing the split in c# using String.Split() and passing the list to SQL will be more efficient than any approach that does the split in SQL
You can write the query as this:
declare #Ids varchar(500) = '12964,12965,12966'
select *
from tblBooks
where ','+cast(BookID as varchar(500))+',' like '%,'+#Ids+',%';
But you don't want to do that because the performance is bad -- the query cannot use indexes.
Three other options. Use dynamic SQL and plug the list directly into the query. Or use a split function to split the string. Or use a table variable:
declare #ids table (id int);
insert into #ids(id)
select 12964 union all select 12965 union all select 12966;
select b.*
from tblBooks b
where b.BookId in (select id from #ids);
This won't work. SQL Server does not split strings for you implicitly and there is no built in string split function in SQL Server either.
If you are driving this via C# you can use Table value parameters. You can also pass your query through Dapper-Dot-Net which will automatically parameterize an "In" query.
If you really must do this in T-SQL, you can also use a string splitting logic here is a relatively concise one.
SELECT i.value('./text()[1]', 'int') [id] into #ids
FROM( values(CONVERT(xml,'<r>' + REPLACE(#Ids+left(##dbts,0),',','</r><r>') + '</r>')) ) a(_)
CROSS APPLY _.nodes('./r') x(i)
select *
from tblBooks a
join #ids i on i.id = a.bookId
Create this function:
CREATE FUNCTION [dbo].[SplitDelimiterString] (#StringWithDelimiter VARCHAR(8000), #Delimiter VARCHAR(8))
RETURNS #ItemTable TABLE (Item VARCHAR(8000))
AS
BEGIN
DECLARE #StartingPosition INT;
DECLARE #ItemInString VARCHAR(8000);
SELECT #StartingPosition = 1;
--Return if string is null or empty
IF LEN(#StringWithDelimiter) = 0 OR #StringWithDelimiter IS NULL RETURN;
WHILE #StartingPosition > 0
BEGIN
--Get starting index of delimiter .. If string
--doesn't contain any delimiter than it will returl 0
SET #StartingPosition = CHARINDEX(#Delimiter,#StringWithDelimiter);
--Get item from string
IF #StartingPosition > 0
SET #ItemInString = SUBSTRING(#StringWithDelimiter,0,#StartingPosition)
ELSE
SET #ItemInString = #StringWithDelimiter;
--If item isn't empty than add to return table
IF( LEN(#ItemInString) > 0)
INSERT INTO #ItemTable(Item) VALUES (#ItemInString);
--Remove inserted item from string
SET #StringWithDelimiter = SUBSTRING(#StringWithDelimiter,#StartingPosition +
LEN(#Delimiter),LEN(#StringWithDelimiter) - #StartingPosition)
--Break loop if string is empty
IF LEN(#StringWithDelimiter) = 0 BREAK;
END
RETURN
END
Then call it like this:
declare #Ids varchar(500) = '12964,12965,12966'
select *
from tblBooks
where BookID in (SELECT * FROM dbo.SplitDelimiterString(#ids,','))
one way is to cast int to varchar. many other ways....
select *
from tblBooks
where CAST(BookID as varchar(50)) in (#Ids)
related: Define variable to use with IN operator (T-SQL)

How can I count the number of columns in a MySQL table using C#?

I can select the number of rows returned by a query when I select everything by doing the following:
SELECT Count(*) FROM `foo`.`bar`;
However, I now want to select how many columns are returned. Is there an easy way to do this?
Use the information_schema database.
SELECT
COUNT(COLUMN_NAME) AS numcols
FROM COLUMNS
WHERE
TABLE_NAME = 'bar'
AND TABLE_SCHEMA = 'foo'
To put the two together, use:
SELECT
(SELECT COUNT(*) FROM foo.bar) AS numrows,
(SELECT
COUNT(COLUMN_NAME) AS numcols
FROM COLUMNS
WHERE
TABLE_NAME = 'bar'
AND TABLE_SCHEMA = 'foo'
) AS numcols
DESCRIBE someTable and then mysql_count_rows() on the result.
Since the question has to do with C#, I think this should work - but I haven't done C# in a long time.
MySqlConnection connection = new MySqlConnection(#...);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "DESCRIBE sometable";
connection.Open();
Reader = command.ExecuteReader();
Reader.FieldCount # this has the count of rows, and hence columns
If your table mydb.mytable is MyISAM, the following should work well:
SELECT
row_count,column_count
FROM
(
SELECT table_rows row_count
FROM information_schema.tables
WHERE table_schema = 'mydb'
AND table_name = 'mytable'
) rowcount,
(
SELECT MAX(ordinal_position) column_count
FROM information_schema.columns
WHERE table_schema = 'mydb'
AND table_name = 'mytable'
) columncount
;

Query with parameters in C# (using SQL Server)

I have a problem with query in C#.
I have this part of code :
string query1 = #"
SELECT TOP #howManyRows * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";
SqlParameter param1 = new SqlParameter();
param1.ParameterName = "#howManyRows";
param1.Value = resultPerPage; //`resultPerPage` is an integer function parameter
SqlParameter param2 = new SqlParameter();
param2.ParameterName = "#startingWith";
param2.Value = startsWith; //`startWith` is an integer function parameter
SqlCommand cmd = new SqlCommand( query1, connect );
cmd.Parameters.Add( param1 );
cmd.Parameters.Add( param2 );
When debug arrived to SqlDataReader reader = cmd.ExecuteReader(); then the exception is thrown:
Incorrect syntax near #howManyRows ...
Why ? I defined and added howManyRows with Parameters property.
Where is my mistakes ?
Change your top query syntax from
SELECT TOP #howManyRows * FROM
to
SELECT TOP (#howManyRows) * FROM
Try wrapping the parameter specified next to TOP in parentheses, like so:
SELECT TOP (#howManyRows) * FROM
You need parenthesis to parametrise TOP
SELECT TOP (#howManyRows) * FROM
This will work.
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ between #startingWith and (#startingWith + #howManyRows)
ORDER BY CATEGORY_
You need to add a couple of parenthesis to make it work.
SELECT TOP (#howManyRows) * FROM
Use SELECT TOP(#howManyRows) syntax
You can do
SELECT TOP (#howManyRows) * FROM
But this really depends on the Database Server you are using. For example, this is only supported from MSSQL Server 2005 upwards
If this does not work you can do the following...
You can include this into your query string. But this can result in Sql Injection if you don't check the value of your variable.
Sample
int top = 10;
Int32.TryParse(howManyRows.ToString(), out top);
string query1 = "SELECT TOP " + top.ToString() + #" * FROM
(
SELECT
PRODUCTCODE_.ID_ AS PRODUCTCODE_ID_,
PRODUCTCODE_.CATEGORY_ AS CATEGORY_,
PRODUCTCODE_.DESCRIPTION_ AS DESCRIPTION_,
PRODUCTCODE_.MANUFACTURER_ AS MANUFACTURER_,
PRODUCTLINE_.CREATION_DATE_ AS CREATION_DATE_,
ROW_NUMBER() OVER (ORDER BY PRODUCTCODE_.CATEGORY_) AS ROWNUMBER_,
TOTALROWS_ = COUNT(*) OVER()
FROM
PRODUCTCODE_
INNER JOIN
PRODUCTLINE_ ON PRODUCTLINE_.ID_ = PRODUCTCODE_.PRODUCTLINE_ID_
) _tmpList
WHERE
ROWNUMBER_ >= #startingWith
ORDER BY CATEGORY_
";

Invalid Column Name though it's there!

I'm trying to print out Tables from the DB that have the EntityId column equals to DataclassId column here is the code
public void getRootTables_checkSP()
{
string connect = "Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes";
SqlDataReader rootTables_List = null;
SqlConnection conn = new SqlConnection(connect);
conn.Open();
SqlCommand s_cmd = new SqlCommand("SELECT * FROM sys.Tables WHERE EntityId = DataclassId", conn);
rootTables_List = s_cmd.ExecuteReader();
while (rootTables_List.Read())
{
string test = rootTables_List[0].ToString();
Console.WriteLine("ROOT TABLES ARE {0}", test);
}
rootTables_List.Close();
conn.Close();
}
but it keeps saying that these columns are invalid though when I printed out all the columns in the DB "syscolumns" they were there...
Can anyone tell me why I'm getting such an error?
EDIT
What I really want is to query the db TacOps_4_0_0_4_test not the system. I just realized that
EDIT 2
Here is an example of the Tables in my DB
Table_1
ID Sequence Type Heigh Weight EntityId DataclassId
0 1 s 1.4 2.5 42-2c-Qi 42-2c-Qi
1 2 s 2.4 2.5 zh-km-xd zh-km-xd
2 3 s 3.4 2.5 8n-tr-l7 8n-tr-l7
Table_2
ID Data Person EntityId DataclassId
0 1 Dave 58-zj-4o 41-2c-Q7
1 2 Sara 99-op-t6 oy-7j-mf
2 3 Silve 75-qy-47 2d-74-ds
Table_3
ID Name Genre EntityId DataclassId
0 LR Ac 78-jd-o9 78-jd-o9
1 OI Dr 4t-jb-qj 4t-jb-qj
2 DH Do 7j-3e-ol 7j-3e-ol
The output should be
Table_1
Table_3
EntityId and DataclassId are indeed no columns that exists in the sys.tables.
You're selecting data from sys.tables, there's no notion of syscolumns in your query, so i do not know why you're mentionning 'syscolumns' in your explanation ?
I think I may understand what you're trying now based on your comment to Frederik's answer
I tried "syscolumns" just to make sure
that the columns do exist. But when I
do the query where EntityId =
DataclassId it says "Invalid column
name
It sounds like EntityId and Dataclassid are columns in a table (or tables) that you have in your database and you want to find the rows from those tables that contain the same value in both those columns??
If that's the case, you are querying sys.Tables incorrectly - you'd need to query the specific tables directly i.e.
SELECT * FROM Table1 WHERE EntityId = DataClassId
Can you clarify?
Edit:
You can find all the tables that contain both those columns using this:
SELECT t.name
FROM sys.tables t
WHERE EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='EntityId')
AND EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='DataClassId')
From this, you could either iterate round each table and run the query to find rows that match on EntityId/DataClassId values - could insert into a temp table and return 1 resultset at the end.
OR, you could create a view to UNION all the tables together and then query that view (would need to update the view each time you added a new table).
OR, you could do some dynamic SQL generation based on the above to generate a SELECT statement on-the-fly to UNION all the tables together.
Update:
Here's a generic way to do it in pure TSQL - this way means if new tables are added it will automatically include them:
DECLARE #SQL VARCHAR(MAX)
SELECT #SQL = COALESCE(#SQL + CHAR(10) + 'UNION ALL' + CHAR(10), '')
+ 'SELECT ''' + REPLACE(QUOTENAME(t.Name), '''', '''''') + ''' AS TableName, COUNT(*) AS RowsMatched FROM ' + QUOTENAME(t.name)
+ ' WHERE EntityId = DataClassId'
FROM sys.tables t
WHERE EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='EntityId')
AND EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='DataClassId')
SET #SQL = 'SELECT x.TableName, x.RowsMatched FROM (' + #SQL + ') x WHERE x.RowsMatched > 0 ORDER BY x.TableName'
EXECUTE(#SQL)
If you don't need it to be dynamic, change the above EXECUTE to a PRINT to see the SQL it generates, and then create a view from it. You can then SELECT from that view.
Of course, you could either loop round each table 1 by 1 as you are trying.
Based on all the comments, i think what you might be trying to find is ALL tables in your database that have both EntityID and DataClassID columns.
I know...its a pretty WILD guess but dont blame me for trying!! :-)
If my shot in the pretty awesome darkness that is your question is correct, try this out:
SELECT tabs.name
FROM sys.tables tabs INNER JOIN sys.columns cols
ON tabs.object_id = cols.object_id
AND cols.name IN ('EntityId', 'DataClassId')
Well, if you do a sp_help 'sys.Tables' in SQL Management Studio you'll see that, indeed, those columns are not part of sys.Tables...

Categories