Im writing a C# web page thats tied to a listview. My client would like to be able to type in something or part of something that it would show results. For example he wants a textbox where he may put in a phone number, part of a phone number, a name, city or whatever and there would be a SP of sorts that finds then lists the info. How can I accomplish this in either a SQL Sp or within VS 2010?
SELECT cols
FROM tbl
WHERE field LIKE '%' + #input + '%'
As several others have suggested, use the LIKE operator.
However, do NOT just put the data the user typed in directly into your LIKE clause like others have suggested. This leads to a very simple and very dangerous vulnerability known as a SQL injection attack.
If you insert the user's input directly into
SELECT cols FROM tbl WHERE field LIKE '%' + input + '%'
then a user could put the following in the text box:
;DROP TABLE tbl; --
(as an example), which makes your SQL statement become:
SELECT cols FROM tbl WHERE field LIKE '%'; (the first part of your query)
DROP TABLE tbl; (the injected sql that you don't want to let people run; drop the database table)
-- '%' (the rest of your previous query is commented out)
Always make sure you used parametrised SQL statements, or at the minimum sanitize your inputs. You really don't want people to be able to run arbitrary SQL on your database server.
Jeff Atwood (of SO fame) has a short posting on this.
And it is worth reading this too :)
Most everyone has hit on part of the solution -- use the LIKE operator.
But I think another aspect of the problem can be addressed in SQL.
Create a computed varchar(MAX) column. Turn on a full text index on this field. Then all you need to do is do a sql like:
SELECT * from <TABLE_NAME> WHERE Keywords like '%<search term>%'
This way you don't have to do phone like <search> or name like <search> etc.
Use the LIKE operator.
SELECT * FROM Table WHERE PhoneNumber LIKE '%value%' OR Name LIKE '%value%' OR
City LIKE '%value%'
If you want to use one textbox which could contain many different kinds of data, you need to be specific in your code about which database tables and columns you will search, and in what order.
For example, you might write a query that does this:
First, search in the Customer table
in the FirstName and LastName columns
for a name LIKE the one in the
textbox. SELECT the CustomerID for
all of the matches.
Next, search in both the Customer
table and the Supplier table, in the
PhoneNumber column, for a phone
number LIKE the one in the textbox.
SELECT the CustomerID or SupplierID
for all of the matches. If any results are found, combine them with the results of the first query.
Continue searching for street
addresses, and querying other tables.
Add new records to the resultset as
you go along.
After you have queried all of the tables that you want to search in, you will have a resultset containing ID's. You need to do another series of SELECTs to get the information you want to display to the user. If you mix customers and suppliers (and employees, etc), this could become quite complicated.
As you can see from this, it would be much easier to have separate textboxes for each search criteria. One textbox for first name, another for last name, a third for company name. A separate textbox for phone number. And if you are mixing data for customers, suppliers, employees, etc, you should have the user indicate (perhaps on a dropdown list or with checkboxes) which types of people to search, so you know which tables to query.
Related
Let say I have a MySQL server with one table that has over 1 million records. For the sake of illustration let say those are products. To make it simple the table has only 3 columns:
product_id - name - price
Let say I have one table displaying the information. Through a TextBox, with each key press, I wan't to select the products that contains the string in that TextBox, additionally the TextBox can have multiple search strings (up to 3) divided by a character '^' so if the TextBox had a string like: "st ^ b ^ ry" it would select products that contains 'st', 'b' and 'ry'.
I made the query like this:
SELECT
product_id,
name,
price
FROM
products
WHERE
name LIKE %{Param1}%
AND name LIKE %{Param2}%
AND name LIKE %{Param3}%
ORDER BY
name ASC
Locally this is fine I guess but when the program is being used somewhere else the query and table takes forever to load after each key press. So...
What is the best way to do this?
Is there a better way to get what i want instead of 3 "LIKE" or is it
right how I did it?
UPDATE
I've checked the questions posted by Loathing and according to what I read the best solution is:
SELECT name FROM table
WHERE MATCH (name) AGAINST ('keyterm');
Having a FULLTEXT index (with MyISAM engine). But the problem with that is that it won't show partial entries. If I had a product called "1/2 Blue Strawberry" and in keyterm I have 'a' (as an example), nothing will show up. I don't want it to just look for words but every record containing whatever I want even if that is a single letter.
I have two access database tables: one called trainers and one called trainerplan. I need to be able to query this database from my c# application in visual studio 2010 and display it. I cannot display the trainers multiple times; I have to display them once and then at the end, display all of the trainerplans they provide.
I can display all the trainers no problem. The problem I have is only display the trainer once with all of their trainer plans at the end. Right now, I am saving all it all into an arraylist.
Here is the query from the database that shows all of the trainers and their plans:
Here is how I need it to look in the application:
I have thought about creating a separate array for just the plans. I would have it check to see if the names are the same and if so, add those plans together. But I'm not sure if that's the right way to go nor really how to do that. I'm not even sure what to search for to get some ideas.
EDIT:
Here is the trainer table
Here is the trainer plan table
I assume that your key to link between those tables names TrainerID and the following SQL Query should work, then you don't have to separate the querying.
SELECT MAX(t.FirstName) AS FirstName,
MAX(t.LastName) AS LastName,
MAX(t.Phone) AS Phone,
MAX(t.[Hours]) AS [Hours],
( SELECT CONVERT(varchar(10), tp.PlanID) + ' '
FROM trainerplan tp
WHERE tp.TrainerID = t.ID
ORDER BY tp.PlanID
FOR XML PATH('') ) AS PlanID
FROM trainers t
GROUP BY t.TrainerID ;
I have a current requirement to determine the table hierarchy from a sql statement within c#. For example, consider the following sql statement:
Select Table1.*, Table2.* from Table1
left join table2 on Table1.parentCol = Table2.childCol
That might return 7 columns, 3 for Table1 and 4 for table2. I need to know the column names, and ideally (though not mandatory) their types.
I have no control over what SQL Statement will be used, as this is a user entered field. In C# it's a very basic task to open a connection and create an SqlCommand using that statement. I have freedom to run the SQL into a SqlDataReader, or any other System.Data.SqlClient class if necessary, however I cannot find any combination that will return the columns, rather than the actual column values.
Is anyone able to help?
Many thanks and best regards
You cannot do what you are asking (easily).
More to the point, do not let users enter arbitrary TSQL (You will regret it at some point...).
Instead, create a 'Search' form that allows entering various params and use a parameterised query onto a view that joins all the tables/columns required.
There's no direct way. You'll need to parse names of all the tables from the sql query.
Once you have done that you'll need to write few queries on Information_Schema to get raw data for what you are looking for.
If you are on SQL Server, you may want to use Catalog View
ex-
Select * from sys.tables where [Name] = 'MyTable'
I am a PHP/MySQL developer, slowly venturing into the realm of C#/SQL Server and I am having a problem in C# when it comes to reading an SQL Server query that joins two tables.
Given the two tables:
TableA:
int:id
VARCHAR(50):name
int:b_id
TableB:
int:id
VARCHAR(50):name
And given the query
SELECT * FROM TableA,TableB WHERE TableA.b_id = TableB.id;
Now in C# I normally read query data in the following fashion:
SqlDataReader data_reader= sql_command.ExecuteReader();
data_reader["Field"];
Except in this case I need to differentiate from TableA's name column, and TableB's name column.
In PHP I would simply ask for the field "TableA.name" or "TableB.name" accordingly but when I try something like
data_reader["TableB.name"];
in C#, my code errors out.
How can fix this? And how can I read a query on multiple tables in C#?
The result set only sees the returned data/column names, not the underlying table. Change your query to something like
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
Then you can refer to the fields like this:
data_reader["Name_TA"];
To those posting that it is wrong to use "SELECT *", I strongly disagree with you. There are many real world cases where a SELECT * is necessary. Your absolute statements about its "wrong" use may be leading someone astray from what is a legitimate solution.
The problem here does not lie with the use of SELECT *, but with a constraint in ADO.NET.
As the OP points out, in PHP you can index a data row via the "TABLE.COLUMN" syntax, which is also how raw SQL handles column name conflicts:
SELECT table1.ID, table2.ID FROM table1, table;
Why DataReader is not implemented this way I do not know...
That said, a solution to be used could build your SQL statement dynamically by:
querying the schema of the tables you're selecting from
build your SELECT clause by iterating through the column names in the schema
In this way you could build a query like the following without having to know what columns currently exist in the schema for the tables you're selecting from
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
You could try reading the values by index (a number) rather than by key.
name = data_reader[4];
You will have to experiment to see how the numbers correspond.
Welcome to the real world. In the real world, we don't use "SELECT *". Specify which columns you want, from which tables, and with which alias, if required.
Although it is better to use a column list to remove duplicate columns, if for any reason you want *****, then just use
rdr.item("duplicate_column_name")
This will return the first column value, since the inner join will have the same values in both identical columns, so this will accomplish the task.
Ideally, you should never have duplicate column names, across a database schema. So if you can rename your schema to not have conflicting names.
That rule is for this very situation. Once you've done your join, it is just a new recordset, and generally the table names do go with it.
I have a medical database that keeps different types of data on patients: examinations, lab results, x-rays... each type of record exists in a separate table. I need to present this data on one table to show the patient's history with a particular clinic.
My question: what is the best way to do it? Should I do a SELECT from each table where the patient ID matches, order them by date, and then keep them in some artificial list-like structure (ordered by date)? Or is there a better way of doing this?
I'm using WPF and SQL Server 2008 for this app.
As others have said, JOIN is the way you'd normally do this. However, if there are multiple rows in one table for a patient then there's a chance you'll get data in some columns repeated across multiple rows, which often you don't want. In that case it's sometimes easier to use UNION or UNION ALL.
Let's say you have two tables, examinations and xrays, each with a PatientID, a Date and some extra details. You could combine them like this:
SELECT PatientID, ExamDate [Date], ExamResults [Details]
FROM examinations
WHERE PatientID = #patient
UNION ALL
SELECT PatientID, XrayDate [Date], XrayComments [Details]
FROM xrays
WHERE PatientID = #patient
Now you have one big result set with PatientID, Date and Details columns. I've found this handy for "merging" multiple tables with similar, but not identical, data.
If this is something you're going to be doing often, I'd be tempted to create a denormalized view on all of patient data (join the appropriate tables) and index the appropriate column(s) in the view. Then use the appropriate method (stored procedure, etc) to retrieve the data for a passed-in patientID.
Use a JOIN to get data from several tables.
You can use a join (can't remember which type exactly) to get all the records from each table for a specific patient. The way this works depends on your database design.
I'd do it with separate SELECT statements, since a simple JOIN probably won't do due to the fact that some tables might have more than 1 row for the patient.
So I would retrieve multiple result-sets in a simple DataSet, add a DalaRelation, cache the object and query it down the line (by date, by exam type, subsets, ...)
The main point is that you have all the data handy, even cached if needed, in a structure which is easily queried and filtered.