What is the difference between quote and double quote in mssql - sql-server

Is there a difference in these two expressions for example?
Select [column] as 'column1' from [table]
Select [column] as "column1" from [table]

Single quotes are for literal strings. Double quotes are the ANSI SQL Delimit Identifier for object names (T-SQL's delimit identifier is brackets ([])).
Don't use single quotes (') for aliases though, as (as mentioned) single quotes are for literal strings, not delimit identifying object names. Single quotes only work as delimit identifiers on aliases when you define said alias, no where else. This means that you can easily confuse those new to the language (and even those who've been using it for years if your formatting is poor).
As an example, ORDER BY 'column1' would not order by your column aliased as 'column1', it would order by the varchar literal 'column1'; effectively your data would not be ordered at all and would be returned in an arbitrary order (as every row has the same value for it ordering). Like wise in the following the 1st statement would return no rows and the second would error:
SELECT 'Column1'
FROM (SELECT [Column] + '_suffix' AS Column1
FROM dbo.MyTable) MT
WHERE 'Column1' LIKE 'ID%';
GO
SELECT 'Column1' + 2
FROM (SELECT [SomeIntColumn] AS 'Column1'
FROM dbo.MyTable) MT;
The first would return no rows as the literal varchar value 'Column1' will never be LIKE 'ID%'. The second would error as although the column has been aliased as 'Column1', and it's name suggests it's an int column, the outer SELECT would try to convert the literal varchar value 'Column1' to an int, and (obviously) that won't work.
Also some syntaxes with literal string aliases are deprecated (specifically 'string_alias' = expression).
Stick to object and alias names that don't need delimit identifying, and if you must delimit identify them use the T-SQL identifier, brackets ([]), or ANSI-SQL's, double quotes ("). column1 does not need identifying, so you should just define is as column1.

Related

SSMS RegEx replace with optional part

I'm trying to separate columns into a separate line form "select", "group by" and "order by" keywords. How can I make the preceeding spaces optional?
Find (requires preceeding spaces):
^{[ ]+}{(SELECT|GROUP BY|ORDER BY)} {[#_a-z0-5]+}
Replace with: \1\2\n\1 \3
Original query (just an example with no logic):
SELECT myColumn
FROM (
SELECT myColumn
FROM foo
GROUP BY myColumn
ORDER BY myColumn
) as bar
GROUP BY myColumn
ORDER BY myColumn
Result (Failed for the main query):
SELECT myColumn
FROM (
SELECT
myColumn
FROM foo
GROUP BY
myColumn
ORDER BY
myColumn
) as bar
GROUP BY myColumn
ORDER BY myColumn
Expected result:
SELECT
myColumn
FROM (
SELECT
myColumn
FROM foo
GROUP BY
myColumn
ORDER BY
myColumn
) as bar
GROUP BY
myColumn
ORDER BY
myColumn
A couple of small changes to your regex gave the correct result for your example:
{^:b*}{(SELECT|GROUP BY|ORDER BY)} {.+}
:b matches space or tab. * matches zero or more occurrences (so keywords at the start of lines will be matched).
I didn't understand the purpose of the restriction on the column list names so replaced it with a generic .+, which seems more reliable.
This solution could probably be made more robust by not relying on a single space between the keyword and the column list:
{^:b*}{(SELECT|GROUP BY|ORDER BY)}:b+{.+}
I think you should use * quantifier after [ ] to make the preceding spaces optional. So the expression will be
^{[ ]*}{(SELECT|GROUP BY|ORDER BY)} {[#_a-z0-5]+}
and replace with same pattern you are using.
\1\2\n\1 \3

LIKE and Equals not working as expected

I am currently trying to find all users in a database where there is a left bracket [ in the user name however when performing a query against the user table using the LIKE operator no rows are returned. If I use the equals = operator then rows are returned.
The issue doesn't appear when using the right bracket ] or other special characters. I want to use the LIKE keyword as I eventually want to use the wildcard functionality to find all users in the table which the character in.
I have isolated the problem out to an example below. FYI Collation is Latin1_General_BIN
-- [ Not Working
DECLARE #Temp TABLE (UserID VARCHAR(10))
INSERT INTO #Temp SELECT 'TEST[DEPT'
SELECT * FROM #Temp WHERE UserID = 'TEST[DEPT' --Returns 1 row
SELECT * FROM #Temp WHERE UserID LIKE 'TEST[DEPT' -- Returns 0 rows
-- ] Working
DECLARE #Temp2 TABLE (UserID VARCHAR(10))
INSERT INTO #Temp2 SELECT 'TEST]DEPT'
SELECT * FROM #Temp2 WHERE UserID = 'TEST]DEPT' --Returns 1 row
SELECT * FROM #Temp2 WHERE UserID LIKE 'TEST]DEPT' -- Returns 1 row
Citing the documentation forLIKE:
Using Wildcard Characters As Literals
You can use the wildcard pattern matching characters as literal characters. To use a wildcard character as a literal character, enclose the wildcard character in brackets.
So do this: SELECT * FROM #Temp WHERE UserID LIKE '%[[]%' if you want to match all rows with a left bracket somewhere in the UserID.
This is because SQL Server's LIKE doesn't comply with the SQL standard and uses an extended "pattern matching" that is a limited subset of a regular expression matching. And because of that the [ has a special meaning in SQL Server (unlike standard SQL) so the [ needs to be escaped.
So you need to use this:
WHERE UserID LIKE 'TEST\[DEPT' ESCAPE '\'
The escape character can be any character you want and it should be one that doesn't occur in the actual value.
SELECT * FROM #Temp WHERE UserID LIKE 'TEST[DEPT'
The query 'delimits' the special character with square brackets, telling the engine to treat it as a normal literal character instead of a character with special meaning. Check here for more info.
Try something like this.
SELECT * FROM #Temp WHERE UserID LIKE '%TEST[[]DEPT%'

Compare comma separated value in comma separated column in sql server with different sequence

I have column in my table that contains the values like that:
1,3,4,2,6,5
I want to check all the values in the above column..
how to do it??
I want to run the query like ths:
select * from table where column contains 1,2,3,4,5,6
I tried to use like operator but it does not work if column has without sequence values..
That's not very efficient, but will do:
select
*
from [table]
where ','+ '1,2,3,4,5,6' +',' like '%,'+ cast(column as varchar(255)) +',%'

Sorting a query, how does thas it work?

Can someone explain to me why this is possible with SQL Server :
select column1 c,column2 d
from table1
order by c,column3
I can sort by column1 using the alias because order by clause is applied after the select clause, but how is it possible to sort by a column that i'm not retreiving ?
Thanks in advance.
All column names from the objects in the FROM clause are available to ORDER BY, except in the case of GROUPing or DISTINCT. As you've indicated the alias is also available, because the SELECT statement is processed before the ORDER BY.
This is one of those cases where you trust the optimizer.
According to Books Online (http://technet.microsoft.com/en-us/library/ms188385(v=sql.90).aspx)
The ORDER BY clause can include items that do not appear in the
select list. However, if SELECT DISTINCT is specified, or if the
statement contains a GROUP BY clause, or if the SELECT statement
contains a UNION operator, the sort columns must appear in the select
list.
Additionally, when the SELECT statement includes a UNION operator, the
column names or column aliases must be those specified in the first
select list.
You can sort by alias' which you define in the select select column1 c and then you tell it to sort by a column that you are not including in the select, but one that still exists in the table. This allows us to sort by expressions of data, without having to have it in the select.
Select cost, tax From table ORDER BY (cost*tax)

ISNULL twice for the same column

Is it possible to use ISNULL twice for the same column?
ISNULL(ISNULL(column, SELECT sum(column2) FROM table WHERE type = '1')), SELECT sum(column2) FROM table WHERE type = '2'))
Or should I be doing this in a different way with IF ELSE somehow? How would that look like?
Look at the coalesce operator. Your query then becomes:
COALESCE(column,
(SELECT sum(column2) FROM table WHERE type = '1'),
(SELECT sum(column2) FROM table WHERE type = '2'))
It returns the first non-null result from its arguments.
Yes, it is possible.
(The issue I see with the expression in the question is unbalanced parens; two extra closing parens)
The ISNULL function takes two arguments. Either (or both) of those arguments can be expressions, and an ISNULL function is an expression. So yes, you can nest ISNULL functions two, three, four, or more levels deep as you need.
A SELECT statement that returns a single row containing a single column can (usually) be used as an expression. And multiple SELECT statements (subqueries) within a query can reference the same table(s) and same column(s).
In many cases, when we see a query of this type, it points either to a model that isn't working well, or it points to looking at a different way of getting an equivalent result.
EDIT
As other answers have pointed out, the more portable, ANSI-standard compliant COALESCE function can be used to return an equivalent result.
These three expressions are equivalent:
ISNULL(ISNULL(a,b),c)
ISNULL(a,ISNULL(b,c))
COALESCE(a,b,c)
which are also equivalent to these (unnecessarily redundant) expressions:
COALESCE(COALESCE(a,b),c)
COALESCE(a,(COALESCE(b,c))
Test case:
create table tst (id int, a int, b int, c int);
insert into tst values
(1,NULL,NULL,NULL)
,(2,21,NULL,NULL)
,(3,NULL,32,NULL)
,(4,NULL,NULL,43)
,(5,51,52,NULL)
,(6,61,NULL,63)
,(7,NULL,72,73)
,(8,81,82,83);
-- SQL Server
SELECT ISNULL(ISNULL(a,b),c) AS t1
, ISNULL(a,ISNULL(b,c)) AS t2
, COALESCE(a,b,c) AS t3
FROM tst
ORDER BY id
-- MySQL
SELECT IFNULL(IFNULL(a,b),c) AS t1
, IFNULL(a,IFNULL(b,c)) AS t2
, COALESCE(a,b,c) AS t3
FROM tst
ORDER BY id
-- Oracle
SELECT NVL(NVL(a,b),c) AS t1
, NVL(a,NVL(b,c)) AS t2
, COALESCE(a,b,c) AS t3
FROM tst
ORDER BY id
Try using COALESCE (if you are using SQL Server). http://msdn.microsoft.com/en-us/library/ms190349.aspx
It will give you the first non-null value from a list of values. Do you need more help structuring the SQL also?

Resources