I have a database which can be modified by our users through an interface. For one field (companyID) they should have the ability to place an asterisk in the string as a wildcard character.
For example, they can put in G378* to stand for any companyID starting with G378.
Now on my client program I'm providing a "full" companyID as a parameter:
SELECT * FROM table WHERE companyID = '" + myCompanyID + "'
But I have to check for the wildcard, is there anything I can add to my query to check for this. I'm not sure how to explain it but it's kinda backwards from what I'm used to. Can I modify the value I provide (the full companyID) to match the wildcard value from in the query itself??
I hope this maked sense.
Thanks!
EDIT: The user is not using SELECT. The user is only using INSERT or UPDATE and THEY are the ones placing the * in the field. My program is using SELECT and I only have the full companyID (no asterisk).
This is a classic SQL Injection target! You should be glad that you found it now.
Back to your problem, when users enter '*', replace it with '%', and use LIKE instead of = in your query.
For example, when end-users enter "US*123", run this query:
SELECT * FROM table WHERE companyID LIKE #companyIdTemplate
set #companyIdTemplate parameter to "US%123", and run the query.
I used .NET's # in the example, but query parameters are denoted in ways specific to your hosting language. For example, they become ? in Java. Check any DB programming tutorial on use of parameterized queries to find out how it's done in your system.
EDIT : If you would like to perform an insert based on a wildcard that specifies records in another table, you can do an insert-from-select, like this:
INSERT INTO CompanyNotes (CompanyId, Note)
SELECT c.companyId, #NoteText
FROM Company c
WHERE c.companyId LIKE 'G378%'
This will insert a record with the value of the #NoteText parameter into CompanyNotes table for each company with the ID matching "G378%".
in TSQL I would use replace and like. ie:
select * from table where companyid like replace(mycompanyid,'*','%');
This is somewhat implementation dependant and you did not mention which type of SQL you are dealing with. However, looking at MS SQL Server wildcards include % (for any number of characters) or _ (for a single character). Wildcards are only evaluated as wildcards when used with "like" and not an = comparison. But you can pass in a paramater that includes a wildcard and have it evaluated as a wildcard as long as you are using "like"
Related
I have this query in our legacy application -
Select * from Customers where Name like ('param')
Problem is when UI user passes param=%, it shows all available customers. Which we want to avoid.
when param = [abc] , it shows all the customers with a,b or c in thier names. We want to avoid this as well.
In fact we want to handle all sort of wild card character searched to avoid SQL Injection.
In java script what is the way I can achieve this, so that I pass only valid Param to my server.
Pay attention to below query:
Select * from Customers where Name like N'%param%'
Instead of like, use =:
where Name = 'param'
= is a lot like like except it doesn't have wildcards -- That is a bit of a joke. You don't want wildcards so don't use the operator that relies on them.
I know that if you want to combine one ore more fields in a dummy field you would say like this.
Select Name & ' ' & Surname as FullName from Customer .
that would return to the dummy column "FullName" the name separated by space and then surname.
BUT what happen if I want to select all the columns as one column with out needing writing explicitly the name of the column that I want to combine . For example
Select * as MyDummyColumn from Customer
is there any way to do something like above ?
Short answer: NO.
Long answer: It depends. In Oracle, for example, I would write a package (or a single procedure) which takes a parameter (tablename), and create a select programmatically, and then use the execute immediate to execute the sql ...
I´m sure, there are similar ways in other db´s.
Or using a programming language like c#, java, vb (.net or even vb6) or whatever there may be, you can generate the sql by code.
Is there any reason why
SELECT * FROM MyTable WHERE [_Items] LIKE '*SPI*'
does not return any records with OleDbAdapter.Fill(DataSet) or OleDbCommand.ExecuteReader()?
When I run the same SQL in MS Access directly, it returns the expected records. Also, in the same code, if I change the SQL to
SELECT * FROM MyTable
all records are returned.
Try changing LIKE to ALIKE and your wildcard characters from * to %.
The Access Database Engine (Jet, ACE, whatever) has two ANSI Query Modes which each use different wildcard characters for LIKE:
ANSI-89 Query Mode uses *
ANSI-92 Query Mode uses %
OLE DB always uses ANSI-92 Query Mode.
DAO always uses ANSI-89 Query Mode.
The Access UI can be set to use one or the other.
However, when using ALIKE keyword the wildcard character is always % regardless of ANSI Query Mode.
Consider a business rule that states a data element must consist of exactly eight numeric characters. Say I implemented the rule as follows:
CREATE TABLE MyStuff
(
ID CHAR(8) NOT NULL,
CHECK (ID NOT LIKE '%[!0-9]%')
);
It is inevitable that I would use % as the wildcard character because Access's CHAR data type and CHECK constraints can only be created in ANSI-92 Query Mode.
However, someone could access the database using DAO, which always uses ANS-89 Query Mode, and the % character would be considered a literal rather than a 'special' character, and the following code could be executed:
INSERT INTO MyStuff (ID) VALUES ('%[!0-9]%');
the insert would succeed and my data integrity would be shot :(
The same could be said by using LIKE and * in a Validation Rule created in ANSI-89 Query Mode and someone who connects using ADO, which always uses ANSI-92 Query Mode, and INSERTs a * character where a * character ought not to be.
As far as I know, there is no way of mandating which ANSI Query Mode is used to access one's Access database. Therefore, I think that all SQL should be coded to behave consistently regardless of ANSI Query Mode chosen by the user.
Note it is not too difficult to code for both using LIKE with the above example e.g.
CHECK (
ID NOT LIKE '%[!0-9]%'
AND ID NOT LIKE '*[!0-9]*'
)
...or indeed avoid wildcards completely e.g.
CHECK (ID LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]')
However, using ALIKE will result in less verbose code i.e. easier for the human reader and therefore easier to maintain.
Also, when the time comes to port to a SQL product that is compliant with SQL Standards, ALIKE ports well too i.e. transforming the ALIKE keyword to LIKE is all that is required. When parsing a given SQL predicate, it is far, far easier to locate the one LIKE keyword in than it is to find all the multiple instances of the * character in text literals. Remember that "portable" does not mean "code will run 'as is'"; rather, it is a measure of how easy it is to move code between platforms (and bear in mind that moving between versions of the same product is a port e.g. Jet 4.0 to ACE is a port because user level security no longer functions, DECIMAL values sort differently, etc).
Change your * to % as % is the wildcard search when using OLE DB.
SELECT * FROM MyTable WHERE [_Items] LIKE '%SPI%'
Try converting your wildcard chars (*) to %
This should sort the issue out.
Jeez, this works!
Thanks a lot.
I just had to replace not like criteria to not alike criteria.
I'm sharing my "story" to help others find this post easier and save them from a two hours search.
Although I've linked the Excel 95-97 xls files to the Access 2010 database, and ran create table and insert into queries to import all data into a database, for some strange reason, the select query couldn't find the strings I've typed.
I tried not like "something" and not like "%something%" with no success - simply didn't work.
L
I was curious since i read it in a doc. Does writing
select * from CONTACTS where id = ‘098’ and name like ‘Tom%’;
speed up the query as oppose to
select * from CONTACTS where name like ‘Tom%’ and id = ‘098’;
The first has an indexed column on the left side. Does it actually speed things up or is it superstition?
Using php and mysql
Check the query plans with explain. They should be exactly the same.
This is purely superstition. I see no reason that either query would differ in speed. If it was an OR query rather than an AND query however, then I could see that having it on the left may spped things up.
interesting question, i tried this once. query plans are the same (using EXPLAIN).
but considering short-circuit-evaluation i was wondering too why there is no difference (or does mysql fully evaluate boolean statements?)
You may be mis-remembering or mis-reading something else, regarding which side the wildcards are on a string literal in a Like predicate. Putting the wildcard on the right (as in yr example), allows the query engine to use any indices that might exist on the table column you are searching (in this case - name). But if you put the wildcard on the left,
select * from CONTACTS where name like ‘%Tom’ and id = ‘098’;
then the engine cannot use any existing index and must do a complete table scan.
I have a problem with a search query I am using my data contains names and information that has apostrophes in various forms (HTML encoded and actual).
So for example I would like an alternative to this:
SELECT * FROM Customers WHERE REPLACE(LastName,'''','')
LIKE Replace('O''Brien,'''','')
This is just an example, what I want is a way where if someone types OBrien or O'Brien this will still work, I need to replace three versions of the character and the data is feed sourced and cannot be changed - what can be done to a query to allow for this kind of search to work.
I have Items with names which work this way which currently have many nested REPLACE functions and cannot seem to find something that will work this way, which is more efficient.
I am using MS SQL 2000 with ASP if that helps.
Edit
Here is the query that needs to match O'Brien or OBrien, this query does this but is too inefficient - it is joined by another for Item Names and FirstName (optional) for matching.
SELECT * FROM Customers
WHERE
REPLACE(REPLACE(REPLACE(LastName,''',''),''',''),'''','')
LIKE
REPLACE(REPLACE(REPLACE('%O'Brien%',''',''),''',''),'''','')
If you want to stay correct and do this in SQL this is probably the best you can do
SELECT * FROM Customers WHERE
LastName LIKE 'O%Brien' AND
REPLACE(LastName,'''','') LIKE 'O''Brien'
You will still get table scans sometimes, due to poor selectivity.
The reason for the first where is to try to use an existing index.
The reason for the second match is to ensure that last names like ObbBrien do not match.
Of course the best thing to do would be not to need the ugly replace. This could be achieved in the app by storing an additional clean lastname column. Or in a trigger. Or in an indexed view.
You could try this:
SELECT *
FROM Customers
WHERE LastName LIKE Replace('O''Brien,'''','%')
This should allow it to use an index as you are not modifying the original column.
For pure SQL, the escaping is entirely unnecessary.
SELECT * FROM Customers WHERE LastName = 'O''Brien'
Use parameters instead of building the queries in code.
If you are using ADO you can use a syntax like this:
Dim cmd, rs, connect, intNumber
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = "your connectionstring"
cmd.CommandText = "SELECT * FROM Customers WHERE LastName LIKE #LastName"
cmd.Parameters.Append cmd.CreateParameter("#LastName",,,,"O'Brien")
Set rs = cmd.Execute
This should perform the query and insert the string O'Brien properly formatted for your database.
Using parameters ensures that all values are properly formatted and it also protects you against sql injection attacks.