I have a sql select like so which returns a datatable:
select * from table1 a join table2 b on a.id=b.id
Both table1 and table2 have a column named itemno .
How do i reference the 2 separate columns? Normally I would use something like:
datarow["itemno"].ToString(); <=first column named itemno only
datarow["b.itemno"].ToString(); <= fail
However this only seems to get the first column named itemno.
Is there a way to reference the second column named itemno without changing my sql statement? (I know i can change my sql statement, take out the * and put in column aliases).
You can reference the columns by index instead:
datarow[0].ToString();
I'd much prefer aliasing them though to be honest.
Given an SQL query like this
select a.id, b.id, a.columnA,a.columnB,a.itemno,b.itemno
from table1 a
join table2 b on a.id=b.id
Your C# code would/could look like this to read all rows and all columns:
using (SqlCommand getAllColumns = new SqlCommand("select a.id, b.id,a.columnA,a.columnB,a.itemno,b.itemno from table1 a join table2 b on a.id=b.id", conn))
{
using (var drreader = getAllColumns.ExecuteReader())
{
DataTable tb = new DataTable();
tb.BeginLoadData();
tb.Load(drreader);
tb.EndLoadData();
foreach(DataRow row in tb.Rows.Cast<DataRow>().ToList())
{
// assuming these are all varchar columns
string idA = (string)row["id"];
string idB = (string)row["id1"];
string columnA = (string)row["columnA"];
string columnB = (string)row["columnB"];
string columnAItemNo = (string)row["itemno"]; //fetches the first itemno column, a.itemno in this case
string columnBItemNo = (string)row["itemno1"]; //fetches the second itemno column, b.itemno in this case
}
}
}
I use this on .NET Framework 4.5. If you want to verify or debug this, put a breakpoint on the foreach line and inspect the DataTable object. The second itemno column should be titled differently compared to the first one.
Related
How to do left join 2 DataTables based on multiple columns match ?
In order to compare what datarows is not matching in the right table
Part of incremental upload need to bring in just the new rows from source Datatable
Found a way to use LINQ to do the comparison of two datatables in c# using join (LEFT)
IEnumerable<DataRow> result = (from srcDt in dtSource.AsEnumerable()
join dstDt in dtDestination.AsEnumerable()
on new { EmployeeID = srcDt["EmployeeID "], Environment = srcDt["Environment"] } equals new { EmployeeID = dstDt["EmployeeID "], Environment = dstDt["Environment"] }
into g
from row in g.DefaultIfEmpty()
where row == null
select srcDt);
// verify if the result has any rows in the dataset
if (result.Any())
{
DataTable dtInserts = result.CopyToDataTable();
// other code which uses the new datarows to perform inserts
}
Have a SQL table example column Id-Pk-int, Name-varchar(250), ...
Using EF Core
when I execute
var data= (from c in _db.Table.FromSql($"select * from Emp where id=1")
select c).FirstOrDefault();
returns successfully
but when I execute using where clause name (string)
var data = (from c in _db.Table.FromSql($"select * from Emp where Name=Mike")
select c).FirstOrDefault();
I get an exception, System.Data.SqlClient.SqlException: 'Invalid column name 'Mike'.'
I tested if I changed the data in the database column: Name to 123 (number) it works but fails when value is string
I think the problem is occured because of you forgot to use ' symbol. Because exception says there is no column named Mike. And column name should be "Name" as i see from the code.
Check if Name column is VARCHAR. If the column is VARCHAR you need use ' symbols. If not you can use like WHERE ID=1
Use that;
var data = (from c in _db.Table.FromSql($"select * from Emp where Name='Mike'")
select c).FirstOrDefault();
Edit 2: I see that you said Id-int, Name-varchar. Can you use the code i wrote? Thanks.
You should use proper parameterization, do not concatenate or interpolate data into a query, or you will leave yourself open to injection attacks and syntax errors.
var data = (from c in _db.Table.FromSql("select * from Emp where Name = #name",
new SqlParameter("#name", SqlDbType.VarChar, 50){Value = "Mike"})
select c).FirstOrDefault();
var data = (from c in _db.Table.FromSql("select * from Emp where Id = #id",
new SqlParameter("#id", SqlDbType.Int){Value = 1})
select c).FirstOrDefault();
In newer versions of EF Core, use FromSqlRaw in the same way.
I have the following SQLite query (using C#):
command.CommandText = #"SELECT
sd.productuid,
sp.productuid,
sp.description as productname
FROM sale_detail sd
JOIN setup_product sp ON 1 = 1";
In this query I get all both tables to see exactly the values of my productuid column.
If you see the result you can verify that the productuid in one table exists in the other:
Now, I do the right join:
command.CommandText = #"SELECT
sd.productuid,
sp.productuid,
sp.description as productname
FROM sale_detail sd
JOIN setup_product sp ON sp.productuid = sd.productuid";
And is empty. This is breaking my head, I don't know why the join is not working even when the productuid in table sale_detail exists in setup_product.
Both fields are uniqueidentifier.
Why is this not working?
I have a DB (in SQL Server 2008 SP3) and need all Schema names, Table names and Column Names in related hierarchy in C# Code, I have the SQLElement Class as Following:
public class SQLElement
{
public string SchemaName { get; set; }
public string TableName { get; set; }
public string ColumnName { get; set; }
}
And have a List Like:
List<SQLElement> SQLElementCollection = new List<SQLElement>();
So how can I read Names from DB and add them to this List (SQLElementCollection)?
for example assume we create a table like this:
Create Table [General].[City] (
[Id] BIGINT NOT NULL IDENTITY(1, 1),
[Title] NVARCHAR(30) NOT NULL DEFAULT (N''),
[Province_Id] BIGINT NOT NULL
)
and I need the list like:
[0]={SchemaName="General", TableName="City", ColumnName="Id"}
[1]={SchemaName="General", TableName="City", ColumnName="Title"}
[2]={SchemaName="General", TableName="City", ColumnName="Province_Id"}
Does any one have any idea about this?
Edit:
In next step how we can get the type of each column or related properties?
My suggestion is to include another member DataType in SQLElement if you have change permission or create another class with a property name DataTypeand then inherit from SQLElement and then save data type name into it for later use and use below query for all information, thanks
SELECT t.name AS TableName,
SCHEMA_NAME(t.schema_id) AS SchemaName,
c.name AS ColumnName,
tp.name as DataType
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types tp ON c.system_type_id = tp.system_type_id
ORDER BY TableName;
Connect to your database and execute the following statement:
select *
from INFORMATION_SCHEMA.COLUMNS
order by TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;
Check the results and then peek and choose what you need.
This query will give you all column names and schema name
SELECT t.name AS tblName,
SCHEMA_NAME(schema_id) AS [schemaName],
c.name AS colName
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
where SCHEMA_NAME(schema_id) = 'dbo' // you can include this where clause if you want to add additional filter to the result set, like query only tables that belong in particular db schema, or query only tables that starts with particular name (maybe prefix or sufix), etc.
ORDER BY tblName;
you have to execute the above query and take results in list
Have a look at the Information_Schema Views in your DB. These have all the stuff you want already in them.
I have a following SQL statement and would like to update Database table if row found.
string sql = "Select A.CNum FROM TABLEA A, TABLEB B WHERE A.CID= B.CID AND A.CNum is NULL AND CID=#cID"
DataTable dt = querySql(sql, params);
if (dt.Rows.Count > 0)
{
// I would like to update CNum from TableA
}
What is the best method to update the row from SQL Statement?
Thank you..
It should be possible to do this in one statement without round-tripping any data from the database and back:
UPDATE
TABLEA
SET
CNum = newValueHere
FROM
TABLEA A,
INNER JOIN TABLEB B ON B.CID = A.CID
WHERE
A.CNum is NULL
AND A.CID=#cID
note I qualified the CID reference in the last line ( I think you'll get an error without this as it exists on both tables, and used an inner join to connect your tables. Note that newValueHere can be an expression of any of the columns in A or B.
Using the SQL from Tom's answer with the following C# will give you what you want.
using(SqlCommand cmd = new SqlCommand(sql, conection))
{
int rowsAffected = cmd.ExecuteNonQuery();
}
you can use EXISTS construct to do this in just one query.
string sql = "IF EXISTS(Select A.CNum FROM TABLEA A, TABLEB B WHERE A.CID= B.CID AND A.CNum is NULL AND CID=#cID) BEGIN ..... END"