We have a class that replaces SQL parameters with their actual HashMap values. For example, select * from x where date = %processingDate% will substitute the value of processingDate and then retrieve the corresponding records. However, it seems to not do the replacement when the parameter name is the same name as the column; for example, select * from x where date = %date% does not substitute date and then retrieves all the records because it's acting like an always true boolean. Is this expected SQL behavior?
Thanks for the help.
Given date is a reserved keyword in T-SQL I would recommend wrapping the column with [] to qualify the column.
Link to list of reserved kewords
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/reserved-keywords-transact-sql
You mentioned SQL Paramater in your question. I would expect your parameter to look like #date if it is a sql parameter. If it does not have the # prefix your query may be evaluating the column and not the parameter that you expect.
I believe something like this would work for you:
--Assuming #date is being evaluated as a string
SELECT *
FROM x
WHERE [date] LIKE '%' + #date + '%'
--Evaluates the specific value (Research differences between like and = operator)
SELECT *
FROM x
WHERE [date] = #date
Related
Say I have a table named 'Parts'. I am looking to create a SQL query that compares the first X characters of two of the fields, let's call them 'PartNum1' and 'PartNum2'. For example, I would like to return all records from 'Parts' where the first 6 characters of 'PartNum1' equals the first 6 characters of 'PartNum2'.
Parts
PartNum1
PartNum2
12345678
12345600
12388888
12345000
12000000
14500000
the query would only return row 1 since the first 6 characters match. MS SQL Server 2017 in case that makes a difference.
If they are strings, use left():
left(partnum1, 6) = left(partnum2, 6)
This would be appropriate in a where, on, or case expression. Note that using left() would generally prevent the use of indexes. If this is for a join and you care about performance, you might want to include a computed column with the first six characters.
you can try something like this. I am assuming datatype as integer. You can set size of varchar based on length of fields.
select *
from Parts
WHERE SUBSTRING(CAST(PartNum1 AS VARCHAR(max)), 1,6) = SUBSTRING(CAST(PartNum2 AS VARCHAR(max)), 1,6)
You can go for simple division to see if the numerator matches for those partnumbers.
DECLARE #table table(partnum int, partnum2 int)
insert into #table values
(12345678, 12345600)
,(12388888, 12345000)
,(12000000, 14500000);
select * from #table where partnum/100 = partnum2/100
partnum
partnum2
12345678
12345600
I want to filter a query in the Where Statement. I want to compare IDs with 'IN' but only if an input has value.
If this text comes empty I don't want to compare. Prevent the error query
EXAMPLE:
StringProductIDs = ''
WHERE
({Issue}.[ServiceRequestId] IN (#StringServiceRequestIDs))
AND ({ServiceRequest}.[Id] IN (#StringServiceRequestIDs))
AND ({Product}.[Id] IN (#StringProductIDs) OR #StringProductIDs = '') /* Is this one that i want to prevent*/
AND EXTRACT(MONTH FROM {Sprint}.[CompleteDate]) = #Month
AND EXTRACT(YEAR FROM {Sprint}.[CompleteDate]) = #Year
In this case, I just want to filter things.id if the value passed as a parameter has value. If it comes empty I don't want to compare and avoid the 'AND' line
Or try another approach:). There is a way to run a query only if this input has value? If it has no value, it returns nothing. If the input has value run normally –
Many thanks
You need OR :
WHERE (things.active = 1 AND things.state = 2) AND
(things.id IN (#INPUT) OR #INPUT IS NULL);
I have one column that called 'message' and includes several data such as fund_no, detail, keywords. This column is in table called 'trackemails'.
I have another table, called 'sendemails' that has a column called 'Fund_no'.
I want to retrieve all data from 'trackemail' table that the column 'message' contains characters same as 'Fund_no' in 'trackemails' Table.
I think If I want to check the equality, I would write this code:
select
case when t.message=ts.fund_no then 1 else 0 end
from trackemails t, sendemails s
But, I do want something like below code:
select
case when t.message LIKE ts.fund_no then 1 else 0 end
from trackemails t, sendemails s
I would be appreciate any advice to how to do this:
SELECT *
FROM trackemails tr
INNER JOIN sendemail se on tr.Message like '%' + se.Fund_No + '%'
Dear Check SQL CHARINDEX() Function. This function finds a string in another string and returns int for the position they match. Like
SELECT CHARINDEX('ha','Elham')
-- Returns: 3
And as you need:
SELECT *
,(SELECT *
FROM sendemail
WHERE CHARINDEX(trackemails.Message,sendemail.Fund_No)>0 )
FROM trackemails
For more information, If you want something much better for greater purposes, you can use Fuzzy Lookup Component in SSDT SSIS. This Component gives you a new column in the output which shows the Percentages of similarity of two values in two columns.
In the SSIS Package I have several Data flow Tasks where I want to use one input global variable named KOERSEL to go back in time and call data set specifically in time.
When I try to run it I am getting the error:
Syntax error, permission violation, or other nonspecific error.
when I change ? to 1 in the SQL command text, the code is running fine. So what am I missing?
DECLARE #dt DATETIMEOFFSET = SWITCHOFFSET(CONVERT(DATETIMEOFFSET, GETDATE()), '-04:00')
DECLARE #interval INT = ?
SET #interval = -1 * #interval
DECLARE #DATE_OPG DATE
SELECT #DATE_OPG = A.DWH_PR_DATO
FROM TABLE AS A
WHERE YEAR(A.DWH_PR_DATO)=YEAR(DATEADD(MONTH,#interval,#dt)) AND
MONTH(A.DWH_PR_DATO)=MONTH(DATEADD(MONTH,#interval,#dt))
ORDER BY A.DWH_PR_DATO DESC
SELECT DISTINCT COLUMN 1,
COLUMN 1,
COLUMN 1,
FROM TABLE 1
WHERE DATE_OPG=#DATE_OPG
UNION ALL
SELECT DISTINCT COLUMN 2,
COLUMN 2,
COLUMN 2,
FROM TABLE 2
WHERE DATE_OPG=#DATE_OPG
...
Screenshot
I don't think that the following error is the real issue.
Incorrect syntax near ')'.
The query parser was not able to parse the query because you have added a minus sign before the question mark ?. In this answer i will try to clarify the main cause of the error you are seeing.
Parameter data type vs Variable data type
Based on the official OLEDB Source - Documentation:
The parameters are mapped to variables that provide the parameter values at run time. The variables are typically user-defined variables, although you can also use the system variables that Integration Services provides. If you use user-defined variables, make sure that you set the data type to a type that is compatible with the data type of the column that the mapped parameter references.
This implies that the parameter datatype is not related to the variable data type.
So when you are using -? inside the SQL Command the query parser are not able to identify the parameter metadata even if it is mapped to an integer variable.
You can check my answer on the link below, it contains much details with experiments:
Date calculation with parameter in SSIS is not giving the correct result
Solving the problem
(1) Force parameter data type
Try using CAST() function to force the parameter data type and assign it to a variable in the same way you have declared #dt:
DECLARE #interval INT = CAST(? as INT)
--If you want to get a negative number else ignore the row below
SET #interval = -1 * #interval
DECLARE #dt DATETIMEOFFSET = SWITCHOFFSET(CONVERT(DATETIMEOFFSET,GETDATE()),'-04:00');
DECLARE #DATE_OPG DATE;
SELECT #DATE_OPG = DWH_PR_DATEO
FROM TableName
WHERE YEAR(DWH_PR_DATO) = YEAR(DATEADD(MONTH,#interval ,#dt)) AND
MONTH(DWH_PR_DATO) = MONTH(DATEADD(MONTH,#interval ,#dt))
ORDER BY DWH_PR_DATO DESC
(2) Using Expressions
You can use Expressions while building the SQL Command:
Add a variable of type string (Example: #[User::strQuery])
Define an Expression within this variable:
"DECLARE #dt DATETIMEOFFSET = SWITCHOFFSET(CONVERT(DATETIMEOFFSET,GETDATE()),'-04:00');
DECLARE #DATE_OPG DATE;
SELECT #DATE_OPG = DWH_PR_DATEO
FROM TableName
WHERE YEAR(DWH_PR_DATO) = YEAR(DATEADD(MONTH,-" + #[User::KOERSEL] + ",#dt)) AND
MONTH(DWH_PR_DATO) = MONTH(DATEADD(MONTH,-" + #[User::KOERSEL] + ",#dt))
ORDER BY DWH_PR_DATO DESC"
In the OLEDB Source choose SQL Command from variable and Select #[User::strQuery]
Experiments
I tried a similar query using the AdventureWorks database:
DECLARE #dt DATETIMEOFFSET = SWITCHOFFSET(CONVERT(DATETIMEOFFSET, GETDATE()), '-04:00')
DECLARE #interval INT = CAST(? as INT)
SET #interval = -1 * #interval
DECLARE #DATE_OPG DATE
SELECT #DATE_OPG = A.[ModifiedDate]
FROM [AdventureWorks2016CTP3].[HumanResources].[Employee] AS A
WHERE YEAR(A.[ModifiedDate])=YEAR(DATEADD(MONTH,#interval,#dt)) AND
MONTH(A.[ModifiedDate])=MONTH(DATEADD(MONTH,#interval,#dt))
ORDER BY A.[ModifiedDate] DESC
SELECT * FROM [AdventureWorks2016CTP3].[HumanResources].[Employee]
WHERE [ModifiedDate] = #DATE_OPG
And the query is parsed successfully
Instead of -? use the following logic:
-1 * (CAST(? as int))
if you just want to pass the variable as parameter without a negative sign then just use:
(CAST(? as int))
You cannot assign a negative sign to the parameter because it will cause some conflict since the query parser will not be able to define the parameter data type.
If it still throwing and exception, check the following link it contains a workaround:
Problem With Parameter Multiplied By Negative Value In Where Clause in OLE DB Source
see if someone can get me this question:
This is my SQL query which loads into a temporary table for which to consult posterirormente there all goes well:
DECLARE #listStr VARCHAR(MAX)
SELECT #listStr = COALESCE(#listStr+' ,' , '') + sCodProducto
FROM dbo.Productos WHERE sCodProducto IN (80063, 80061, 80067, 80062, 80065)
INSERT INTO #IDPROD2(CODIGO)
SELECT #listStr
if I make this a select shows me the following data:
SELECT * FROM #IDPROD2
Well, now if I consult so this brings me nothing:
SELECT * FROM dbo.Productos P WHERE P.sCodProducto IN (SELECT CODIGO FROM #IDPROD2)
now if it works this way:
SELECT * FROM dbo.Productos P WHERE P.sCodProducto IN (80061 ,80062 ,80063 ,80065 ,80067)
A field in a query result is considered a single VALUE. The actual contents of that field are irrelevant. Doesn't matter if you have a numbers in CSV format, or one single number - that entire chunk of data is one single VALUE, as far as the DB is concerned.
Since it's a single value, your codigo field's contents are parsed/executed as:
... WHERE foo IN (#codigo)
... WHERE foo IN ('1,2,3,4,...');
... WHERE foo = '1,2,3,4,....';
The DB will NOT parse those values, and therefore will NOT treat string as multiple distinct values.
If you want the contents of a single field or variable to be treated as multiple distinct values, you have to use dynamic sql:
sql = "SELECT .... WHERE foo IN (" + #codigo + ")";
exec #sql;
Note that this is basically a form of SQL injection. You remove the "context" of being a single value from that variable field, and force the DB to treat it as multiple different values.
Some DBs get around this by providing extract functions, e.g. mysql's find_in_set, which is designed specifically for this:
SELECT ... WHERE FIND_IN_SET('80063', '80063, 80061, 80067, 80062, 80065');
There is no such function in TSQL, but can be simulated, even with a simple like query:
... WHERE foo='80063' OR foo LIKE '80063,%' OR foo LIKE '%,80063,%' OR foo LIKE '%,80063'