Search using single input while searching multiple tables - c#

I need to make a search button for ASP.NET C# web site. Making a button with 1 kind of search key is easy. For example:
Select * from table where name like '%' + search_criteria + '%'
But what I really need is to make a search button that will contain more "like" from different though tables. I have in my DB
Category.Category_Name nchar
Product.Description nchar
Product.Product_Cost float
Manufacturer.Manufacturer_Name nchar
And you can see which ones are in which table. Also with the help of GridView I want to show on my webpage only the first 3. But I want a single textBox with a single button and when I try to search something, search either category name or description or cost or manufaturer name all in 1.
I have read that you can only search multiple things from one table or use contain statement in order to search from different tables. I've looked many hour in internet but in vain. Can someone help me figure out what do I need to right in WHERE clause so I can put that in aspx.cs C# code in LIKE filter and have my button worked?

I don't know if this exactly answers your question, but I will try. Although, to be fair, it is not supremely clear what you need and the question is bordering Too Broad
void btnSearch_Click (object sender, EventArgs e)
{
string sql = "select Product_name from Product p inner join Category c on p.Category_id = c.Category_id WHERE c.Category_Name Like '%{0}%' UNION ALL " +
"select Product_name from Product where Description Like '%{0}%' UNION ALL " +
"select Product_name from Product p inner join Manufacturer m on p.Manufacturer_id = m.Manufacturer_id WHERE m.Manufacturer_id Like '%{0}%' ";
decimal price;
if (decimal.TryParse(txtSearch.Text.Trim(), out price)
sql += "UNION ALL select Product_name from Product where Product_Cost >= {0} "
Search(string.Format(sql, txtSearch.Text.Trim());
}
void Search (string sql)
{
// use your sql here to fill the grid, etc.
}
NOTE #JoelCoehoorn noted about possibility of Sql Injection with this code [which is security concern]. I don't know if you care about it at this time. But to prevent Sql Injection you will need to use query parametrization. There will need to be slight change to the query but more changes to Command object setup.

Related

Appending data in T-SQL

I have a sql (transact sql - SQL server 2012) which used to fetch names of customers from a table (Customer) who has valid addresses (from table Details):
Select Customer.Name, Details.Address
from Customer
left outer join Details on Details.Customer = Customer.Name
This used to send back each record (name) row for each customer every time from the db server. No multiple records are fetched.
Recently I needed to modify this sql text in order to fetch even the name of the books they have borrowed as per the database, which is saved in another table (Lending). Now the script looks like:
Select Customer.Name, Details.Address, Lending.BookName
from Customer
left outer join Details on Details.Customer = Customer.Name
left outer join Lending on Lending.CustomerName = Customer.Name
It is returning the records properly, but now I have got a problem. Since a customer can borrow multiple books, the returned data has multiple rows for the same customer showing multiple book names. According to my software specification I need to fetch one line for each customer and in that one row i need to append all the book names in a single column.
Can someone help me with this: How to append multiple data for same record in a single column such as:
Name Address BookName
Somdip XX Brief History of Time,Headfirst SQL,Headfirst C#
instead of
Name Address BookName
Somdip XX Brief History of Time
Somdip XX Headfirst SQL
Somdip XX Headfirst C#
??
I used the above sql text with 'where' and 'order by' clauses such as :
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table] where ID = '1' order by Name) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
and it is giving me an error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
try this:
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table]) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
While I think this is generally a bad idea - returning multiple data items in a single cell - there are a number of ways to go about it, with different performance concerns.
What you're looking for is here: Concatenate many rows into a single text string?

How to Join single table to it self in SQL Server 2008?

I am using below table structure, I want to create a view which will show a FirstName of ReportsTo field shown below.
Please let me give a suggestion how to create that view which will display all the reports to 's first name with (',') comma separator.
You join a table to itself just like any other join. The main this is to make sure both tables are aliased with differnt aliases
Your problem is that you have a one to many relationship stored in the table which is a huge design mistake. For the future, remember that anytime you think about storing information a comma delimted list, then you are doing it wrong and need a related table instead. So first you have to split the data out into the related table you should have had instead with two columns, EmplCode and ReportsTo (with only one value in reports to), then you can do the join just like any other join. We use a function that you can get by searching around the internet called fn_split to split out such tables when we get this type of infomation in client files.
If you search out fn_split, then this is how you can apply it:
Create table #UnsplitData (EmpCode varchar (10), ReportsTo varchar(20), FirstName varchar (10))
insert into #UnsplitData
values ('emp_0101', 'emp_0102,emp_0103', 'John')
, ('emp_0102', 'emp_0103', 'Sally')
, ('emp_0103', Null, 'Steve')
select *, employee.FirstName + ', ' + Reports.FirstName
from #UnsplitData Employee
join
(
select t.EmpCode , split.value as Reportsto, ReportName.Firstname
from #UnsplitData t
cross apply dbo.fn_Split( ReportsTo, ',') split
join #UnsplitData ReportName
on ReportName.EmpCode = split.value
) Reports
On Employee.EmpCode = Reports.empcode
From what I gather, I think you're trying to get the Firstname column and the ReportsTo column separated by a comma:
SELECT FirstName + ', ' + ReportsTo
FROM table
Edit: judging from the comments he's trying to do something else? Can someone rephrase for me?
SELECT E.*,
R.FirstName
FROM Employees E
JOIN Employees R
ON E.ReportsTo LIKE '%' + R.EmpCode + '%'

Ms Access 2010 issue with a where clause in C#

I have a complex select statement for an Access 2010 database which grabs data from multiple tables using several LEFT JOIN statements. The query works as expected and I get the entire table.
So now I want to add search functionality.
One way was to add a WHERE clause at the end of the query and reference one of the JOINed tables' text field and compare it against some text (WHERE [All Names].Name LIKE "*Mark*").
Second option I tried was select * from (**complex sql here**) where **condition**
Now in both cases, when my condition is something simple like ([ID]<15), it works like a charm, but when I change it to ([Employee Name] LIKE "\*Mark\*") or the one in option 1, it produces an empty data table as if the request goes through, there is no error or exception, all the field names are present, but no rows are returned.
However, if I grab the full string of the generated SQL string (either option) using the debugger (or just dump it into a text file), and then with literally no changes put that string directly into a new Access query, it works fine and returns several fields where the name contains "Mark"
Very simply put, a query that works fine within Access, does not work from within C#.
So I am now confused
You're using OleDb to connect to the Access db file. In that situation you must use ANSI wild cards (% and _) for a Like comparison instead of * and ?.
Use a pattern like this in your WHERE clause.
WHERE [Employee Name] LIKE "%Mark%"
If you want a query which works the same within an Access session as it does from an OleDb connection, use ALIKE instead of LIKE. ALIKE always uses the ANSI wild cards.
WHERE [Employee Name] ALIKE "%Mark%"
Simon's question and HansUp's answer ended up solving my problem.
For those curious or having a similar problem, here is full query:
string query=
"SELECT Employees.ID, " +
"[All Names E].Name AS [Employee Name], " +
"Titles.Title, " +
"[All Names S].Name AS [Supervisor Name], " +
"Employees.[Phone #], " +
"Offices.[Office Location], " +
"PCs.PC " +
"FROM (((((Employees LEFT JOIN [All Names] as [All Names E] ON Employees.Employee = [All Names E].ID) " +
"LEFT JOIN [All Names] as [All Names S] on Employees.Supervisor=[All Names S].ID) " +
"LEFT JOIN Titles on Employees.Title=Titles.ID) " +
"LEFT JOIN Offices on Employees.[Office Location]=Offices.ID) " +
"LEFT JOIN PCs on Employees.PC=PCs.ID) " +
"ORDER BY Employees.ID";
Adding a where clause before ORDER BY that is WHERE ([All Names E].Name LIKE \"*Mark*\") did work from within Access.
The second way was:
string searchQuery="select * from ("+query+") where ([Employee Name] like \"*Mark*\")";
Both methods worked perfectly in Access, but I had no idea there was a different wildcard symbol for use with OleDB.
So changing the asterisk to a percentage sign fixed the issue.
Thanks again.

How can I Select all rows where column contain any words of a string

I started by asking this question I wish to Select all rows which contain any element from an array
And while my current question is almost identical, it serves a whole different purpose, and so I fear the answer may be different which would obscure the previous one, with that said.
I am working on a search engine type thing. I need to search a title stored in a database to see if it contains any of the words in the search textbox. I plan to then iterate through each of those rows, counting how many words match and ranking the results accordingly. I am sure this has been done many times by now. I just can't seem to figure out how to do it without
select * from table
then sorting it in c#
one way in sql server is
push the word in temp table like this
DECLARE #SearchWords TABLE (
word varchar(30) )
INSERT INTO #SearchWords
(word)
VALUES ('Jack')
,('Pontiac')
,('Bloggs');
than join this table with the actual table
SELECT a.* FROM table_data a
INNER JOIN #SearchWords b on a.record_desc like '%' + b.word + '%'
You could try something like this:
SELECT * FROM table WHERE name LIKE '%word1%' OR name LIKE '%word2%';
The % signs are the analogous to * in typical searches.
To take the string and create this query for multiple words you could do something like this:
String inputString = "hello my friend";
String[] wordlist = inputString.split(" ");
String query = "SELECT * FROM table WHERE 0=0 ";
for(String word : wordlist) {
query += "OR name LIKE '%" + word + "%' ";
}
The spaces at the end of the strings are important, don't forget those! Also, you'll probably want to sanitize the string before you split it (remove extra punctuation, maybe even remove words like "a" or "the" or "to" etc.)

SQL ORACLE - Datatable in where clause

Currently I have a sql call returning a dataset from a MSSQL database and I want to take a column from that data and return ID's based off that column from the ORACLE database. I can do this one at a time but that requires multiple calls, I am wondering if this can be done with one call.
String sql=String.Format(#"Select DIST_NO
FROM DISTRICT
WHERE DIST_DESC = '{0}'", row.Table.Rows[0]["Op_Centre"].ToString());
Above is the string I am using to return one ID at a time. I know the {0} can be used to format your value into the string and maybe there is a way to do that with a datatable.
Also to use multiple values in the where clause it would be:
String sql=String.Format(#"Select DIST_NO
FROM DISTRICT
WHERE DIST_DESC in ('{0}')", row.Table.Rows[0] ["Op_Centre"].ToString());
Although I realize all of this can be done I am wondering if theres an easy way to add it all to the sql string in one call.
As I am writing this I am realizing I could break the string into sections then just add every row value to the SQL string within the "WHERE DIST_DESC IN (" clause...
I am still curious to see if there is another way though, and because someone else may come across this problem I will post a solution if I develop one.
Thanks in advance.
The most RDBMS-agnostic approach you could do is to create a temporary table. Then just query: select * from district where dist_desc in (select dist_desc from temp_table)
There's a solution here in Oracle http://forums.oracle.com/forums/thread.jspa?threadID=930372 , but I don't have Oracle in my box, so I can't try how it will work in .NET.
Have tried this in Postgresql http://fxjr.blogspot.com/2009/05/npgsql-tips-using-in-queries-with.html , have very seamless support for comparing value to list
If you will go the dynamic query approach, try this:
String sql=String.Format(#"Select DIST_NO
FROM DISTRICT
WHERE DIST_DESC IN ({0})",
string.Join( ",",
ds.Tables[0].Select()
.Select(r => "'" + (string)r["Op_Centre"] + "'").ToArray() ) // string.Join
); // string.Format
K I understand its pointless to ask a question and then answer it yourself but by asking the question I realized the answer.
String sql = "Select DIST_NO FROM DISTRICT WHERE DIST_DESC in ('" +ds.Tables[0].Rows[0]["Op_Centre"].ToString()+"'";
for (int i = 1; i < ds.Tables[0].Rows.Count;i++ )
{
sql +=",'"+ds.Tables[0].Rows[i]["Op_Centre"].ToString()+"'";
}
sql += ")";
I am still curious to see if there is a better way though...

Categories

Resources