I am trying to query from multiple tables in one query.
Although my code is working for one table, I don't know how to search in the second table too.
using (DataTable dt = new DataTable("Uniclass2015_EF_v1_12; Uniclass2015_En_v1_26"))
{
using (SqlCommand cmd = new SqlCommand (" select *from Uniclass2015_En_v1_26 where title like #Title; select *from Uniclass2015_EF_v1_12 where title like #Title", conn))
{
cmd.Parameters.AddWithValue("code", txtSearch.Text);
cmd.Parameters.AddWithValue("Title", string.Format("%{0}%", txtSearch.Text));
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
adapter.Fill(dt);
dataGridView1.DataSource = dt;
}
}
conn.Close();
private void txtSearch_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)13) // enter
BtnSearch.PerformClick();
}
I tried to add a second table to my original code, but however when I type in the search box my query I receive a blank answer.
looks like you're wanting to use the UNION operator in SQL:
https://www.w3schools.com/sql/sql_union.asp
SELECT * FROM Uniclass2015_En_v1_26 WHERE title LIKE #Title UNION
SELECT * FROM Uniclass2015_EF_v1_12 WHERE title LIKE #Title
This of course assumes the columns of the two tables are the same. If you only need specific columns from each, just select those columns.
Also, I don't see where you're using that code parameter you're adding
Related
I implemented a search of my nested gridview, and All is working well. But when the gridview loads, it is displaying duplicate rows in the parent table.
As you can see in the picture, There are 2 books under the CourseID of AC107. But my Gridview is displaying a row for each textbook in the course. I have messed with this select statement and anyway I alter it to see if anything works, the gridview doesnt load.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//i'm using a datatable for storing all the data
DataTable dt = new DataTable();
string query = "select * from Course inner join textBooks on textBooks.CourseID = Course.CourseID";
//wrapping in 'using' means the connection is closed an disposed when done
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["HUTDMSConnectionString"].ToString()))
using (SqlDataAdapter adapter = new SqlDataAdapter(query, connection))
{
try
{
//fill the datatable with the contents from the database
adapter.Fill(dt);
}
catch
{
}
}
//save the datatable into a viewstate for later use
ViewState["allBooks"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
Below is a layout of my data tables.
Are you sure your SQL query not fetching you the duplicate rows, use ROW_NUMBER() function and see how it works like (assuming you are using SQL Server since you are using SqlConnection provider class)
SELECT * FROM (
select Course.*,
ROW_NUMBER() OVER(PARTITION BY Course.CourseID ORDER BY Course.CourseID) AS rn
from Course
inner join textBooks
on textBooks.CourseID = Course.CourseID ) xxx
WHERE rn = 1;
I need to populate a datagrid with the following columns.
invnumber,itemname,rate,quantity..
itemname,rate,quantity comes from 1 table while invnumber comes from another table
I used to do like this
string commandText = "SELECT invnumber,cname,date FROM inv_table WHERE invnumber LIKE #id";
SqlCommand command = new SqlCommand(commandText, conn);
string searchParam = String.Format("%{0}%", text_inv.Text);
command.Parameters.AddWithValue("#id", searchParam);
using (SqlDataAdapter sda = new SqlDataAdapter(command))
{
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
dataGridView2.DataSource = dt;
}
}
Now i cannot directly assign the data source as 2 different tables are involved
dataGridView2.DataSource = dt;
How can i get around this.
To emit combined result from 2 or more different tables in a table, use either INNER JOIN, LEFT JOIN, RIGHT JOIN or UNION statement depending on your need.
In this case, you need to join first table and other table to get desired results, assume invnumber is unique or primary key. Here is an example:
string commandText = "SELECT other.invnumber, inv.cname, inv.date FROM inv_table AS inv
INNER JOIN other_table AS other
ON inv.invnumber = other.invnumber
WHERE other.invnumber LIKE #id";
Or if you have already defined classes for each table, use LINQ to SQL with lambda expression:
DataContext dc = new DataContext();
var results = dc.InvTable.Join(OtherTable, inv => inv.invnumber, other => other.invnumber, (inv, other) => new { invnumber = other.invnumber, cname = inv.cname, date = inv.date });
Any improvements and suggestions welcome.
Create a new class for the data structure of the 2 different table, populate the new one and use. (easier and the most clear solution)
I have a datagridview (dgvSelectedItem)and I want it to display some values from textboxes but I have this error
Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound
My code is:
DataTable dt = new DataTable();
string conn = "server=.;uid=sa;pwd=123;database=PharmacyDB;";
Okbtn()
{
SqlDataAdapter da = new SqlDataAdapter("select UnitPrice from ProductDetails where prdctName like '"+txtSelectedName.Text + "'", conn);
da.Fill(dt);
dgvSelectedItem.DataSource = dt;
//this code work but when I add these lines the Error appear
dgvSelectedItem.Rows.Add(txtSelectedName.Text);
dgvSelectedItem.Rows.Add(txtSelectedQnty.Text); }
Thanks in advance
UPDATED Per OP Comment
So you want a user to enter the product name and quantity, then to run a query against the database to retrieve the unit price information. Then you want to display all of that information to your user in a DataGridView control.
Here is what I suggest:
Include the prdctName field in your SELECT clause.
If you want to bind all relevant data to a DataGridView including the Quantity variable and your TotalPrice calculation, then include them in your SELECT statement. When you bind data to the control from an SQL query like this, the result set is mapped to the grid. In other words, if you want information to be displayed when setting the DataSource property then you need to include the information in your SQL result set.
Don't use LIKE to compare for prdctName as it slightly obscures the purpose of your query and instead just use the = operator.
In addition from a table design perspective, I would add a UNIQUE INDEX on the prdctName column if it is indeed unique in your table - which I sense it likely is. This will improve performance of queries like the one you are using.
Here is what your SQL should look like now:
SELECT prdctName, UnitPrice, #Quantity AS Quantity,
UnitPrice * #Quantity AS Total_Price
FROM ProductDetails
WHERE prdctName = #prdctName
A few other suggestions would be to use prepared SQL statements and .NET's using statement as already noted by Soner Gönül. I'll try to give you motivation for applying these techniques.
Why should I use prepared SQL statements?
You gain security against SQL Injection attacks and a performance boost as prepared statements (aka parameterized queries) are compiled and optimized once.
Why should I use the using statement in .NET?
It ensures that the Dispose() method is called on the object in question. This will release the unmanaged resources consumed by the object.
I wrote a little test method exemplifying all of this:
private void BindData(string productName, int quantity)
{
var dataTable = new DataTable();
string sql = "SELECT prdctName, UnitPrice, #Quantity AS Quantity, " +
"UnitPrice * #Quantity AS Total_Price " +
"FROM ProductDetails " +
"WHERE prdctName = #prdctName";
using (var conn = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue("#prdctName", productName);
cmd.Parameters.AddWithValue("#Quantity", quantity);
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dataTable);
dataGridView1.DataSource = dataTable;
}
}
}
}
Here's a sample input and output of this method:
BindData("Lemon Bars", 3);
I searched over the internet and looks like there is no way to add new rows programmatically when you set your DataSource property of your DataGridView.
Most common way is to add your DataTable these values and then bind it to DataSource property like:
da.Fill(dt);
DataRow dr = dt.NewRow();
dr["UnitPrice"] = txtSelectedName.Text;
dt.Rows.Add(dr);
dt.Rows.Add(dr);
dgvSelectedItem.DataSource = dt;
Also conn is your connection string, not an SqlConnection. Passing SqlConnection as a second parameter in your SqlDataAdapter is a better approach in my opinion.
You should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Finally, don't forget to use using statement to dispose your SqlConnection and SqlDataAdapter.
I assume you want to use your text as %txtSelectedName.Text%, this is my example;
DataTable dt = new DataTable();
using(SqlConnection conn = new SqlConnection("server=.;uid=sa;pwd=123;database=PharmacyDB;"))
using(SqlCommand cmd = new SqlCommand("select UnitPrice from ProductDetails where prdctName like #param"))
{
cmd.Connection = conn;
cmd.Parameter.AddWithValue("#param", "%" + txtSelectedName.Text + "%");
using(SqlDataAdapter da = new SqlDataAdapter(cmd, conn))
{
da.Fill(dt);
DataRow dr = dt.NewRow();
dr["UnitPrice"] = txtSelectedName.Text;
dt.Rows.Add(dr);
dt.Rows.Add(dr);
dgvSelectedItem.DataSource = dt;
}
}
I'm trying to learn some C#.net. I'm just trying to expose the AdventureWorks database included in my C# class via a web interface. Here's the setup:
I've got a DropDownList in on my ASPX page with an id of tableNameDropDown. It gets populated on Page_Load like this:
protected void Page_Load(object sender, EventArgs e)
{
conn.Open();
String table_names_sql = "select Name from sysobjects where type='u' ORDER BY name";
SqlCommand cmd = new SqlCommand(table_names_sql, conn);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
tableNameDropDown.Items.Add(reader[0].ToString());
}
conn.Close();
tableNameDropDown.AutoPostBack = true;
}
And that works just fine, I get a nice long list of the tables in the DB. When someone selects a table from the list, I want to display that table in a GridView control with an id of grid. This is what I've got:
protected void tableNameDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
DataSet dataSet = new DataSet();
String tableName = columnNameDropDown.SelectedItem.ToString();
String table_sql = String.Format("SELECT * FROM {0};", tableName);
SqlDataAdapter adapter = new SqlDataAdapter(table_sql, conn);
adapter.Fill(dataSet, tableName);
grid.DataSource = dataSet;
grid.DataMember = tableName;
}
When I debug the page, I get an error on the adapter.Fill(dataSet, tableName); line: SqlException: Inlvalid object name '{tableName}'.
The tables in the DB are the following:
dbo.AWBuildVersion
.... more dbo. tables
HumanResources.Department
HumanResources.Employee
.... more HumanResources tables
Person.Address
Person.AddressType
.... more Person tables
... Other prefixes are "Pdoduction, Purchasing, Sales"
There are probably ~50+ tables, and I get all their names (without the prefixes) into my DropDownList no problem, but I can't seem to query them.
Any ideas?
You've already answered yourself: you need to use also the prefix in the select statement you're executing, like
Select * From Person.Address
Beside that you should not use the sysobject tables, from SQL Server 2005 you have system views that helps you, so you can write a better statement to select tables:
select * From INFORMATION_SCHEMA.TABLES
Check also this article.
Regards
Massimo
I am using sqlconnection. I want to create a view and select from the view set.
Like I have shown below I have created a view called vwtopic.. from this I need to select distinct values of a column.
I cannot put in one easy statment because i need distinct values of topic column only and need to order by another column datetime..
So I am first creating a view where I am ordering by datetime and from this I am selecting distinct topic.
Problem is I am able to create a view set, but from this I am not able to select the distinct topic data to a SqlDataAdapter.. I frankly dont know the syntax.. I have not tried this before..
First part:
SqlConnection con = new SqlConnection("server=xxxx;database=wbsd;user id=***;password=***;");
SqlCommand add = new SqlCommand("CREATE VIEW vwtopic AS SELECT * FROM sr_topic_comment ORDER BY datetime DESC", con);
try
{
add.Connection.Open();
add.ExecuteNonQuery();
add.Connection.Close();
}
catch (System.FormatException)
{
}
Second part:
String sqlcmd = "SELECT DISTINCT topic FROM vwtopic WHERE owner='" + owner + "'";
SqlDataAdapter adap = new SqlDataAdapter(sqlcmd,con);
Instead of creating Views in Code, use the "WITH" statement or Sub-queries this should meets your needs:
WITH [vwtopic] AS (
SELECT * -- I recommend using each column name
FROM [sr_topic_comment]
-- not sure if ORDER BY is allowed here:
-- ORDER BY [datetime] DESC
)
SELECT DISTINCT [topic] FROM [vwtopic] -- add WHERE, ORDER BY
Since the view you are creating does not have any filters defined, selecting distinct values from the view is equivalent to selecting distinct values from the table. When selecting distinct values, you can only order by those values (not the datetime column as you're attempting here). Therefore, you can do:
SqlCommand cmd = new SqlCommand("SELECT DISTINCT topic FROM sr_topic_comment WHERE owner = #owner", con);
cmd.Parameters.Add(new SqlParameter(#owner, SqlDbType.Varchar, 25));
cmd.Parameters["#owner"].Value = owner;
DataSet ds = new DataSet();
using (SqlDataAdapter adap = new SqlDataAdapter(cmd)) {
adap.Fill(ds);
}
This will give you a DataSet filled with the distinct values from the table that meet the filter criteria (owner == the supplied owner).
I found the answer below will do the trick for me...
I am filling the result in dataset and calling my required column 'topic'..
SELECT DISTINCT topic,datetime FROM sr_topic_comment WHERE owner='sr' ORDER BY datetime DESC
Thank you very much for your inputs.. I learnt about WITH clause today.. cheers..