How to use literal backslash in SQL query statement? - sql

EDIT2: Sorry everyone, problem solved. I WAS trying to concatenate a number with my string. I forgot that I simplified my statement when I posted here, thinking my problem had to do with the backslash rather than type compatibility. You guys are right and I was being an idiot. Thanks!
I'm using Access 2013 where my query pulls its data from a SQL 10.0 server (using pass-through).
I am trying to use the backslash in my SQL query like below (***edit: tbltask.jobnum is a string in my database):
SELECT [tblEstimator].[Name] + '\\20' + [tbltask].[JobNum] + ' JOBS\\' AS JobMidFilePath
But when I run the query, I get the error:
Conversion failed when converting the varchar value '\\20' to data type smallint. (#245)
I have no idea what this means or why it's trying to convert anything to smallint.

To replicate your issue, we can write a query something like this:
declare #name varchar(50) = 'Test',
#JobNum smallint = 12
select #name + '\\20' + #JobNum + ' JOBS\\';
This will return the same error:
Conversion failed when converting the varchar value 'Test\20' to data
type smallint.
But if you convert the smallint or the number field to a string like this, the error should go away:
declare #name varchar(50) = 'Test',
#JobNum smallint = 12
select #name + '\\20' + cast(#JobNum as varchar(10)) + ' JOBS\\'
Your query should look something like this:
SELECT [tblEstimator].[Name] + '\\20' + cast([tbltask].[JobNum] as varchar(10))
+ ' JOBS\\' AS JobMidFilePath
I am not sure the equivalent of MS-ACESS on this, but that should resolve your issue.

/*You can copy/paste directly into SQL, comments will be commented out ini SQL syntax
I would create a temp table to achieve this. */
USE whateverDB
GO
CREATE TABLE #toSelectFrom (
Name VARCHAR (100)
,JobNum TINYINT
/*look at the schema, it'll tell you what the data type is in SQL tables, in the column folder [see image] (http://i.ytimg.com/vi/MKPtdjq3MzA/maxresdefault.jpg) - copy verbatim to your temp table columns */
,slashPathNumber VARCHAR (25)
,slashPathJobs VARCHAR (50)
)
INSERT INTO #toSelectFrom (Name, slashPathNumber, JobNum, slashPathJobs)
SELECT [tblEstimator].[Name], '\\\\20', [tbltask].[JobNum], ' JOBS\\' AS JobMidFilePath /*** FROM yourTableToSelectFrom -- you NEED THIS FOR VALID SQL! ***/
--Then just:
SELECT * FROM #toSelectFrom;
-- OR Alternatively:
SELECT Name + slashPathNumber + JobNum + slashPathJobs AS JobMidFilePath FROM #toSelectFrom;
/*
If you use it a lot, just write the above select statement(s) into a view to select from more often. ;)
*/

First off, you can try to cast/convert your int as your output should be string. If the single quote doesn't work, you can try using double qoute (")
SELECT [tblEstimator].[Name] + "\\20" + CAST([tbltask].[JobNum] as varchar(100)) + " JOBS\\" AS JobMidFilePath

Related

How to create a function SQL that returns a string from a table?

How can I create a function like this?
function FN_something (#entrada char(50))
declare #consulta table
declare #notificacao varchar(50)
declare #multa float
declare #saida varchar(50)
set #consulta as = (select num_notificacao,num_multa from table where field = #entrada)
set #notificacao = #consulta.num_notificacao
set #multa = #consulta.num_multa
set #saida = "resultado: "+ #notificacao +";"+#multa
return #saida
Thanks in advance
I would not use a function... Scalar functions tend to be a real performance killer. Try to use something like this inline
SELECT 'resultado: '
+ ISNULL(CAST(t.num_notificacao AS VARCHAR(MAX)),'???')
+ ';'
+ ISNULL(CAST(t.num_multa AS VARCHAR(MAX)),'???')
FROM SomeTable AS t WHERE t.SomeField=#entrada;
If you need a function it was much better to use an inlined TVF (syntax without BEGIN...END and bind it into your query with CROSS APPLY.
Might be simplified:
If your columns are NOT NULL you can go without ISNULL()-function. If your columns are strings, you can do without CAST()... My code is defensive proramming :-D
Hint
If this is something you need more often, you might introduce a VIEW carrying this calculated column and use it instead of your table. You might include this value into your table as computed column as well...
UPDATE
Great, the VIEW you show in the comment is an inline TVF actually, which is very good!
My magic crystall ball tells me, that you might need something like this:
SELECT cl.*
,'resultado: ' + t.num_notificacao + ';' + t.num_multa AS CalculatedResult
FROM dbo.[CampoLivre876]('SomeParameter') AS cl
LEFT JOIN SomeOtherTable AS t ON cl.entrada=t.SomeField --should be only one related row per main row!
This will call the iTFV and join it to the other Table, where the two columns are living. I Assume, that the CampoLivre876-row knows its entrada key.
Hint 2:
If this works for you, you might include this approach directly into your existing iTVF.
UPDATE 2
You might try to change your function like here:
ALTER FUNCTION [dbo].[CampoLivre876] ()
RETURNS TABLE
RETURN
Select cl.mul_numero_notificacao + ';' + CAST(cl.mul_valor_multa as varchar(max)) AS ExistingColumn
,'resultado: ' + t.num_notificacao + ';' + CAST(t.num_multa AS varchar(max)) AS CalculatedResult
From Campo_Livre AS cl With(NoLock)
INNER JOIN SomeOtherTable AS t ON cl.entrada=t.SomeField;
This should read all lines in one go. Reading 1 row after the other is - in almost all cases - something really, really bad...
Here is an example of a function with correct SQL Server syntax:
create function FN_something (
#entrada char(50) -- should probably be `varchar(50)` rather than `char(50)`
) returns varchar(50)
begin
declare #saida varchar(50);
select #saida = 'resultado: ' + num_notificacao + ';' + num_multa
from table
where field = #entrada;
return #saida;
end;
Note: This assumes that the num_ columns are strings, not numbers. If they are numbers, you need to convert them or use concat().
EDIT:
A function really isn't appropriate for this. Probably the best solution is a computed column:
alter table t add something as (concat('resultado: ', num_notificacao, ';', num_multa);
Then you can get the value directly from the table. In earlier versions of SQL Server, you would use a view rather than computed column.

Concate Primary Keys in SQL

I want to concate Primary Keys of multiple tables in SQL directly. I used below query to concate three primary keys with a hyphen between them but the SQL skipped the hyphen and sum up the primary keys and result in a single value.
SELECT CID + '-' + RID + '-'+ CGID As [IdCombination] ...
where CID , RID and CGID are the Primary Keys of three SQL Tables.
How it skipped the string part in query ?
Any help would be highly appreciated.
Updated
For Example : The Values of CID , RID and CGID are 3 , 4, 3 respectively. It should be 3-4-3 but the result is 10.
What is happening? Remember that + means both addition and string concatenation. It so happens that - can be interpreted as a number (like -0), so SQL Server prefers to interpret the + as addition.
Normally, when you do this type of operation, the separation character cannot be interpreted as a number, and you just get an error. I am amused that you don't get an error in this case.
One method is to explicitly cast the values as strings:
SELECT CAST(CID as VARCHAR(255)) + '-' + CAST(RID + as VARCHAR(255)) '-'+ CAST(CGID as VARCHAR(255)) As [IdCombination]
In SQL Server 2012+, you can do this more simply using CONCAT():
SELECT CONCAT(CID, '-', RID, '-', 'CGID) As [IdCombination]
CONCAT() knows that everything should be a string.
Try this
SELECT 5 + '-' + 8
The output is 13. I must admit, that I did not expect this...
And now try this
SELECT CAST('-' AS INT)
The result is 0. As your select starts with an INT, SQL Server tries to do a summa of int values. As the single hyphen is casteable to int implicitly, this returns the summa of your values...
The solution, as pointed out by others is either a cast of your column values to a string type or the usage of CONCAT
I would need to see output, but I am assuming, some ID is stored as int and it is being counted, so you should use
SELECT Cast(CID as Varchar(50)) + '-' + Cast(RID as Varchar(50)) + '-'+ Cast(CGID as Varchar(50)) As [IdCombination]

Escape SQL function string parameter within query

I have a SQL view that calls a scalar function with a string parameter. The problem is that the string occasionally has special characters which causes the function to fail.
The view query looks like this:
SELECT TOP (100) PERCENT
Id, Name, StartDate, EndDate
,dbo.[fnGetRelatedInfo] (Name) as Information
FROM dbo.Session
The function looks like this:
ALTER FUNCTION [dbo].[fnGetRelatedInfo]( #Name varchar(50) )
RETURNS varchar(200)
AS
BEGIN
DECLARE #Result varchar(200)
SELECT #Result = ''
SELECT #Result = #Result + Info + CHAR(13)+CHAR(10)
FROM [SessionInfo]
WHERE SessionName = #Name
RETURN #Result
END
How do I escape the name value so it will work when passed to the function?
I am guessing that the problem is non-unicode characters in dbo.Session.Name. Since the parameter to the function is VARCHAR, it will only hold unicode characters, so the non-unicode characters are lost when being passed to the function. The solution for this would be to change the parameter to be NVARCHAR(50).
However, if you care about performance, and more importantly consistent, reliable results stop using this function immediately. Alter your view to simply be:
SELECT s.ID,
s.Name,
s.StartDate,
s.EndDate,
( SELECT si.Info + CHAR(13)+CHAR(10)
FROM SessionInfo AS si
WHERE si.SessionName = s.Name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') AS Information
FROM dbo.Session AS s;
Using variable concatenation can lead to unexpected results which are dependent on the internal pathways of the execution plan. So I would rule this out as a solution immediately. Not only this, the RBAR nature of a scalar UDF means that this will not scale well at all.
Various ways of doing this grouped concatenation have been benchmarked here, where CLR is actually the winner, but this is not always an option.

parsename is not working when using string from function

Parsename is working when directly using string or returning static value from the function. But when I returning select value with dot from the function. its not working. I am not able to figure out the issue.
CREATE TABLE [dbo].[TestTimeLine](
[UserID] [int] NOT NULL,
[Field1] [nchar](250) NOT NULL,
[Value] [smalldatetime] NULL,
[Timestamp] [datetime] NULL,
)
INSERT INTO [TestTimeLine] VALUES(10,'TestDate',GETDATE(),GETDATE())
CREATE FUNCTION TestFunction()
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #R NVARCHAR(MAX)
SELECT TOP 1 #R=CAST(DATENAME(month,value) AS VARCHAR) + ' ' + CAST(YEAR(value) AS VARCHAR) + '.' +CONVERT(varchar,value,101) + '. ' + LTRIM(Field1)
FROM [TestTimeLine]
WHERE UserId = 10
RETURN #R
END
select dbo.TestFunction()
select PARSENAME(dbo.TestFunction(),2)
Working
select PARSENAME('January 2015.01/05/2015. TestDate',2)
NotWorking -- Returns NULL
select PARSENAME(dbo.TestFunction(),2)
Try changing the parameter 2 to 1.
select PARSENAME(dbo.TestFunction(),1)
For more details refer to:
More Details
The problem is that return value of dbo.TestFunction() is incorrect identifier - it exceeds maximal length limitation for object identifiers in SQL Server. Your sample return value has many trailing spaces which cause this situation.
In general, this is not good idea to use PARSENAME for your purpose because you are using the function not for its initial purpose so you have all side effects which are not predictable from one SQL Server version to another. Use ordinary string functions in your case.
I got the Issue.
Issue is [nchar] datatype.
After Changing to 'Varchar' datatype. Its working fine.

SQL Server Fulltext Search contains phrase problem

I have a problem with SQL Server 2008 full text search I have the following query
SELECT *
FROM cigars
WHERE CONTAINS(cigars.*, #Search )
#Search is a value that is passed in through a stored procedure. But, thats not the problem.
What is is if someone searches for say 'Punch' it works fine and I get all cigars that match.
Where the problem lays is if they search for 'Punch Cigar' I get this error.
Syntax error near 'Cigar' in the full-text search condition 'Punch Cigar'.
Any idea on how I can get it to allow for it to search for that phrase?
Why are you searching by all columns in the CIGAR table? Surely some of them do not use a string/text based data type...
After looking at the CONTAINS documentation, I'd look at a function to properly escape the words for the FTS searching:
CREATE FUNCTION [dbo].[escapeFTSSearch] (
#SearchParameter NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
-- Declare the return variable here
DECLARE #result NVARCHAR(MAX)
SELECT #result = '"'+ REPLACE(REPLACE(#SearchParameter,'"',''), ' ', '" AND "') +'"'
-- Return the result of the function
RETURN #result
END
Test:
SELECT [example].[dbo].[escapeFTSSearch] ('Punch Cigar')
...which gives me:
"Punch" AND "Cigar"
Usage:
WHERE CONTAINS(cigars.*, dbo.escapeFTSSearch(#Search) )
Addendum
The function is simplistic:
it assumes you want all words provided
doesn't support fuzzy searching
assumes double quotes aren't in the parameter value
Tweak as needed.
You need to ensure you have leading and trailing double quotes ans spaces. i.e. the value of #Search should be ' "Punch Cigar" '
Further to OMG's comments about escaping you would definitely need to strip out any embedded double quotes.
declare #Search varchar(1000)
set #Search = 'punch and" cigar'
set #Search = ' "' + REPLACE(#Search,'"','') + '" '
select * from sys.dm_fts_parser(#Search,1033,null,0)