We have front-end app where user enters customer and/or PO to retrieve data.
For instance, if user want to retrieve all POs for a customer, he will enter '%' in PO field.
If user wants to retrieve all data, he will enter '%' in every field.
I am trying this, but it does not work
SELECT *
FROM PO_INFO
WHERE customer_id = case when '%' then customer_id else 'Macys' end
AND purchase_order = case when '%' then purchase_order else '79124' end
What am I missing?
You should not (some would say must not) just plug the user-entered search values into your SQL query as literals. That is,
AND purchase_order = case when '%' then purchase_order else '79124' end
... is not going to perform or scale well because every single search looks to Oracle like a brand new SQL query that has to get parsed and optimized (i.e., "hard parsed). This is an expensive process that also requires a lot of latches, meaning multiple users trying to run searches at the same time will have to wait for each other.
Instead, you should construct your SQL using bind variables. So,
AND purchase_order = :1 -- or something. We'll discuss the exact logic later...
That :1 is a bind variable, a placeholder for a value your code will supply when it submits the query. Now, everyone doing a search is using the same query (just each supplying different values for the bind variables). No more excessive hard parsing and performance disaster averted.
But, here is the next problem. One query for all means it only gets hard parse one time (good) but it also means everyone runs using the same execution plan. But in a search like this, one size does not fit all. Suppose the execution plan Oracle comes up with uses an index on column 'ABC'. If a user does not supply a bind variable value for column 'ABC', that execution plan will still be followed, but with terrible results.
So, what we want really is one SQL for each set of bind variables that have values or don't, but not one SQL for each distinct set of literal search values.
Build your SQL in code by starting with this string:
SELECT * FROM PO_INFO WHERE 1=1
Then, for each search condition add this (if the value is %)
AND (:1 IS NULL) -- and pass `NULL`, not "%" as the value for :1
(Aside: the reason for this condition, which is essentially NULL IS NULL is to make to so the number and order of the bind variables that have to be passed in is always the same, regardless of what the end user does or does not give you a value for. This makes it much easier to submit the SQL in some languages, like PL/SQL).
If the search condition is not %, add this:
AND (customer_id /* or whatever column */ = :1) -- and pass the user-entered value
So, for example, if the user specified values for customer_id and po_date but not purchase_order, your final SQL might look like:
SELECT *
FROM PO_INFO
WHERE 1=1
AND customer_id = :1
AND po_date := 2
AND :3 IS NULL -- this is purchase order and :3 you will pass as null
If you do all this, you'll get the least amount of hard-parsing and the best execution plan for each search.
One of my columns is called from. I can't change the name because I didn't make it.
Am I allowed to do something like SELECT from FROM TableName or is there a special syntax to avoid the SQL Server being confused?
Wrap the column name in brackets like so, from becomes [from].
select [from] from table;
It is also possible to use the following (useful when querying multiple tables):
select table.[from] from table;
If it had been in PostgreSQL, use double quotes around the name, like:
select "from" from "table";
Note: Internally PostgreSQL automatically converts all unquoted commands and parameters to lower case. That have the effect that commands and identifiers aren't case sensitive. sEleCt * from tAblE; is interpreted as select * from table;. However, parameters inside double quotes are used as is, and therefore ARE case sensitive: select * from "table"; and select * from "Table"; gets the result from two different tables.
These are the two ways to do it:
Use back quote as here:
SELECT `from` FROM TableName
You can mention with table name as:
SELECT TableName.from FROM TableName
While you are doing it - alias it as something else (or better yet, use a view or an SP and deprecate the old direct access method).
SELECT [from] AS TransferFrom -- Or something else more suitable
FROM TableName
Your question seems to be well answered here, but I just want to add one more comment to this subject.
Those designing the database should be well aware of the reserved keywords and avoid using them. If you discover someone using it, inform them about it (in a polite way). The keyword here is reserved word.
More information:
"Reserved keywords should not be used
as object names. Databases upgraded
from earlier versions of SQL Server
may contain identifiers that include
words not reserved in the earlier
version, but that are reserved words
for the current version of SQL Server.
You can refer to the object by using
delimited identifiers until the name
can be changed."
http://msdn.microsoft.com/en-us/library/ms176027.aspx
and
"If your database does contain names
that match reserved keywords, you must
use delimited identifiers when you
refer to those objects. For more
information, see Identifiers (DMX)."
http://msdn.microsoft.com/en-us/library/ms132178.aspx
In Apache Drill, use backquotes:
select `from` from table;
If you ARE using SQL Server, you can just simply wrap the square brackets around the column or table name.
select [select]
from [table]
I have also faced this issue.
And the solution for this is to put [Column_Name] like this in the query.
string query= "Select [Name],[Email] from Person";
So it will work perfectly well.
Hi I work on Teradata systems that is completely ANSI compliant. Use double quotes " " to name such columns.
E.g. type is a SQL reserved keyword, and when used within quotes, type is treated as a user specified name.
See below code example:
CREATE TABLE alpha1
AS
(
SEL
product1
type_of_product AS "type"
FROM beta1
) WITH DATA
PRIMARY INDEX (product1)
--type is a SQL reserved keyword
TYPE
--see? now to retrieve the column you would use:
SEL "type" FROM alpha1
I ran in the same issue when trying to update a column which name was a keyword. The solution above didn't help me. I solved it out by simply specifying the name of the table like this:
UPDATE `survey`
SET survey.values='yes,no'
WHERE (question='Did you agree?')
The following will work perfectly:
SELECT DISTINCT table.from AS a FROM table
Some solid answers—but the most-upvoted one is parochial, only dealing with SQL Server. In summary:
If you have source control, the best solution is to stick to the rules, and avoid using reserved words. This list has been around for ages, and covers most of the peculiarities. One tip is that reserved words are rarely plural—so you're usually safe using plural names. Exceptions are DIAGNOSTICS, SCHEMAS, OCTETS, OFFSETS, OPTIONS, VALUES, PARAMETERS, PRIVILEGES and also verb-like words that also appear plural: OVERLAPS, READS, RETURNS, TRANSFORMS.
Many of us don't have the luxury of changing the field names. There, you'll need to know the details of the RDBM you're accessing:
For SQL Server use [square_braces] around the name. This works in an ODBC connection too.
For MySQL use `back_ticks`.
Postgres, Oracle and several other RDBMs will apparently allow "double_quotes" to be used.
Dotting the offending word onto the table name may also work.
You can put your column name in bracket like:
Select [from] from < ur_tablename>
Or
Put in a temprary table then use as you like.
Example:
Declare #temp_table table(temp_from varchar(max))
Insert into #temp_table
Select * from your_tablename
Here I just assume that your_tablename contains only one column (i.e. from).
In MySQL, alternatively to using back quotes (`), you can use the UI to alter column names. Right click the table > Alter table > Edit the column name that contains sql keyword > Commit.
select [from] from <table>
As a note, the above does not work in MySQL
Judging from the answers here and my own experience. The only acceptable answer, if you're planning on being portable is don't use SQL keywords for table, column, or other names.
All these answers work in the various databases but apparently a lot don't support the ANSI solution.
Simple solution
Lets say the column name is from ; So the column name in query can be referred by table alias
Select * from user u where u.from="US"
In Oracle SQL Developer, pl/sql you can do this with double quotes but if you use double quotes you must type the column names in upper case. For example, SELECT "FROM" FROM MY_TABLE
I am transfering from access to oracle and couldn't find a roughly equals function in oracle. Does such a thing exist?
I am referring to something like:
SELECT * FROM Table WHERE name ='*nswer is thi*';
Use LIKE:
SELECT * FROM Table WHERE name LIKE '%nswer is thi%';
Explanation:
This query will select records which contains "nswer is thi" anywhere in the field name.
For example:
name
--------------------
answer is this
blahnswer is thiblah
The LIKE conditions specify a test involving pattern matching. Whereas the equality operator (=) exactly matches one character value to another
Read more here.
How can I select only distinct records, from relational table, when using with() operator in Yii?
I'm getting my models (records) like that:
$probe = Probes::model()->with(array
(
'user',
'results',
'results.answer',
'survey',
'survey.questions',
'survey.questions.question',
'survey.questions.question.answers',
'manager'
))->findByPk($id);
I want to make sure, that survey.questions relation returns only distinct records. But it seems, that I don't see any way to achieve this (or I'm blind / not educated enough).
When giving relational table name / alias as array:
'results.question'=>array('alias'=>'results_question'),
the distinct key is not among those, that can be used in such array (as modifier).
I tried very ugly, bumpy way of changing select from default * to DISTINCT *:
'survey.questions'=>array('select'=>'distinct'),
But this has (of course?) failed:
Active record "SurveysQuestions" is trying to select an invalid column "distinct". Note, the column must exist in the table or be an expression with alias.
How can I achieve this (seemed so obvious and easy), if it is possible at all this way (using with())? If not, then -- please, advice how to get distinct records in relational table any way (other than manually filtering results using foreach, what I'm doing right now, and what is ugly).
You could set CDbCriteria::distinct to true:
'survey.questions'=>array('distinct'=>true),
While working with one of the oracle query, when i am firing a select command with where condition something like:
select * from table_name where contains(address,'"IN%" AND "BÖDEN%"') >0
No results are shown as part of this query though results are there in database.
Again if i introduce one space between "IN" and "%" i am getting results in proper:
select * from table_name where contains(address,'"IN %" AND "BÖDEN%"') >0
There is one more scenario :
Same type of query but if "IN" is replaced with "IM" the corresponding results are displayed.
select * from table_name where contains(address,'"IM%" AND "BÖDEN%"') >0
or
select * from table_name where contains(address,'"IM %" AND "BÖDEN%"') >0
Both above queries are giving same results. which is quite obvious too.
Hence i suspect there is something speacial with "IN" in oracle.
Can anybody suggest me proper reason for this problem and any resolution for the problem ?
The IN keyword is a stop word in the default Stoplist which is used to specify the words which are not be indexed in Oracle Text.
You need to remove it from the stop list in order to search such stop words.
Check the link for Stoplist
Also please find the other default Stop words for English in oracle for your reference Default Stop words