How to correctly set expression Query.CommandText in SSRS? - sql-server

In my SSRS report builder I have an expression set for one of my dataset (name is dsTagAttributes). The query type is text.
This is the query expression
="select m.TagName, ta.descriptor, t.[State] from MasterTags m inner join TagAttributesClassic ta on m.ID = ta.TagID inner join TagStates t on t.ID = m.StateID where m.PIServerID = #ServerID and t.[State] = #State and m.MetaData1 = #Station " & Parameters!AndOr.Value & "m.MetaData2 = #Device"
The above query expression has a parameter which is concatenated in the select statement.
The parameter #AndOr data type is text, has a default value of "or", and parameter visibility is set to hidden (screen shot below). I have set this parameter because it will be used to dynamically change the dataset result from or to and during the report runtime.
But when I run the report, an exception is thrown saying,
What could go wrong in my query command text?
Any help is greatly appreciated.

You can run Profiler against Data Source to see the query.
I assume the problem is that you miss "'" before and after each varchar value (#State, #Station).
I wouldn't use that way to use OrAnd condition
You can modify TSQL like
...
AND
(m.MetaData2 = #Device AND #OrAnd = 'AND')
)
OR
(m.MetaData2 = #Device AND #OrAnd = 'OR')
Just make sure you place ')' and '(' correctly, depending on business logic.

Related

Use of Variable in Snowflake Stored Procedure

I have to add a variable MaxDate in my SQL Stored Proc (shown below). The code gets errored out since MaxDate is not represented by its value. Any idea on how I can pass a variable in a stored proc?
create or replace procedure Load_Employee()
returns varchar not null
language javascript
EXECUTE AS CALLER
as
$$
//Variable Initialization
var IntegrationTable ='EMPLOYEE';
var TypeID=0;
var MaxDate=' ';
var cmd = "Select max(COMPLETED_DATE) from SCHEMA.TABLE where TARGET_TABLE_NAME= " + "'" + IntegrationTable + "'" ;
var sql = snowflake.createStatement({sqlText: cmd});
var result = sql.execute();
result.next();
MaxDate=result.getColumnValue(1);
var cmd=` Insert into PersonTable
select SHA1(concat(Person_id,'|','Person')) ,12345678,SHA1(concat('Payroll','|','Pay','|', Load_Date)) ,current_timestamp() , Tenant
from Schema.PERSONTABLE where Date_Added >= MaxDate
where TYPE='ABC' ;`;
$$
;
If your query to get MaxDate works right, then the value should be in the variable. The problem is it's not being replaced in the sql variable defining the insert statement.
Since you're using backticks to open and close the string, you can use a special JavaScript notation to replace the variable with its value, ${MaxDate}.
Your definition of the insert statement would look like this:
var cmd=` Insert into PersonTable
select SHA1(concat(Person_id,'|','Person')) ,12345678,SHA1(concat('Payroll','|','Pay','|', Load_Date)) ,current_timestamp() , Tenant
from Schema.PERSONTABLE where Date_Added >= ${MaxDate}
where TYPE='ABC' ;`;
If that doesn't work, try cutting the SP short with return MaxDate; to see what got assigned to that variable. Also it's very helpful to check the query history view to see what SQL actually ran inside a stored procedure.
Also, I think this is the same SP that was having an issue with a null return. You'll need to return a string value using something like return 'Success'; or something to avoid getting an error for the null return. That's because of the returns varchar not null in the definition.

Executing part of stored procedure based on condition

I am trying to load to a table based on load types - Full or Incremental that is being passed as parameter in stored procedure. I was able to try with substitution variable with one line of code previously, but the below code doesn't seem to work -
Stored procedure possible arguments:
LOAD_TYPE=FULL
LOAD_TYPE=INCR
var incr_condition = (load_type=='INCR')?"INNER JOIN temp_table"
with temp_table(
select data
from table a
where dt between 01-01-2019 and 09-09-2020
)
select *
from table b
${incr_condition} -- execute only if load_type=INCR
INNER JOIN TABLE C ON B.ID = C.ID
Is there any way to restrict the with clause to execute only if the load_type==INCR? Please advice.
I think the conditional operator (question mark) must have a false part in addition to the true part. Otherwise, it generates a syntax error when there's a semicolon ending the line. This example obviously doesn't run anything, but it will return the values assigned to the "out" variable, which would be run.
Since you're using a replacement variable ${incr_condition} be sure to use backticks to open and close your SQL string.
create or replace procedure foo(LOAD_TYP string)
returns string
language javascript
as
$$
var load_type = LOAD_TYP;
var incr_condition = (load_type === 'INCR') ? "INNER JOIN temp_table" : "";
var out = `
with temp_table(
select data
from table a
where dt between 01-01-2019 and 09-09-2020
)
select *
from table b
${incr_condition} -- execute only if load_type=INCR
INNER JOIN TABLE C ON B.ID = C.ID
`;
return out;
$$;
call foo('INCR'); --Adds the inner join
call foo('FULL'); --Does not add the inner join
I also recommend changing your comparison on strings from == to ===. For details on why, reference What is the correct way to check for string equality in JavaScript?.

SSMS Error "An expression of non-boolean type specified in a context where a condition is expected, near '('"

I am getting the titled error from a number of SQL Server views I am trying to create. They are modified from a MS Access database I'm upgrading to use SQL as the back end. See SQL below:
SELECT dbo.Site_Info_All.SiteID,
IIf(dbo.Site_Info_All.Fixed_Charge, N'Yes', N'No') AS [Fixed Charge],
dbo.Site_Info_All.Fixed_Charge_Date, dbo.MG_Definition.MG_Definition
FROM dbo.MG_Definition INNER JOIN
dbo.Site_Info_All ON dbo.MG_Definition.MG_DefinitionID =
dbo.Site_Info_All.MG_DefinitionID
It looks as though I'm being told that the Fixed_Charge field is not boolean, except that it is. I'm encountering this issue with multiple views. What am I doing wrong?
It's not boolean. It's a bit. :)
A bit column doesn't directly evaluate to true or false, the way a bool does in other languages. You actually have to compare it to another bit value to return the boolean value.
declare #bit bit = 1;
if (#bit) print '#bit was true'; -- this does not work
if (#bit = 1) print '#bit = 1 was true'; -- this works
What you want is:
... IIf(dbo.Site_Info_All.Fixed_Charge = 1, N'Yes', N'No') ...
SELECT dbo.Site_Info_All.SiteID,
IIf(dbo.Site_Info_All.Fixed_Charge = 1, N'Yes', N'No') AS [Fixed Charge],
dbo.Site_Info_All.Fixed_Charge_Date,
dbo.MG_Definition.MG_Definition
FROM dbo.MG_Definition
INNER JOIN dbo.Site_Info_All ON dbo.MG_Definition.MG_DefinitionID = dbo.Site_Info_All.MG_DefinitionID
In the end, I decided that IIF simply wasn't working for whatever reason. An answer to that would be very welcome, btw.
I used
SELECT dbo.Site_Info_All.SiteID,
CASE WHEN dbo.Site_Info_All.Fixed_Charge = 1
THEN N'Yes'
ELSE N'No'
END AS [Fixed Charge], dbo.Site_Info_All.Fixed_Charge_Date,
dbo.MG_Definition.MG_Definition
FROM dbo.MG_Definition INNER JOIN
dbo.Site_Info_All ON dbo.MG_Definition.MG_DefinitionID =
dbo.Site_Info_All.MG_DefinitionID
That gave me the results I was after, but only after pulling out what little hair I have left.

Boolean expressions in SQL Server jobs

I have inherited a SQL Server "job" that does several things. There are two "steps" and each has multiple statements one is:
UPDATE Person
SET Person.LastName = P.LastName,
Person.FirstName = P.FirstName,
Person.MiddleName = P.MiddleName,
Person.EmailAddress = P.EmailAddress,
Person.StartDate = P.StartDate,
Person.EndDate = P.EndDate
FROM OtherDB.dbo.Person Person
INNER JOIN FirstDB.dbo.Persons AS P ON P.PersonId = Person.PersonId
WHERE Person.LastName != P.LastName
OR Person.FirstName != P.FirstName
OR Person.MiddleName != P.MiddleName
OR Person.EmailAddress != P.EmailAddress
OR Person.StartDate != P.StartDate
OR Person.EndDate != P.EndDate;
It is updating "person" data from FirstDB into OtherDB. The PersonId columns are bigints and are not null. The various "date" columns are of type datetime and could be NULL. The other columns are all varchar and could be NULL.
What I have learned is that, in the where clause, if NULL appears on either or both sides of the boolean operator the result is undefined. Basically, NULL can neither equal nor not-equal NULL. It appears that the same applies to NULL and any other non-null value.
So I thought to try:
UPDATE Person
SET Person.LastName = P.LastName,
Person.FirstName = P.FirstName,
Person.MiddleName = P.MiddleName,
Person.EmailAddress = P.EmailAddress,
Person.StartDate = P.StartDate,
Person.EndDate = P.EndDate
FROM OtherDB.dbo.Person Person
INNER JOIN FirstDB.dbo.Persons AS P ON P.PersonId = Person.PersonId
WHERE ISNULL(Person.LastName, '') != ISNULL(P.LastName, '')
OR ISNULL(Person.FirstName, '') != ISNULL(P.FirstName, '')
OR ISNULL(Person.MiddleName, '') != ISNULL(P.MiddleName, '')
OR ISNULL(Person.EmailAddress, '') != ISNULL(P.EmailAddress, '')
OR ISNULL(Person.StartDate, '') != ISNULL(P.StartDate, '')
OR ISNULL(Person.EndDate, '') != ISNULL(P.EndDate, '');
This works in a regular query window but fails in the job. The error is:
An expression of non-boolean type specified in a context where a condition is expected, near 'OR'. [SQLSTATE 42000] (Error 4145). The step failed.
I am not seeing a problem. What am I missing?
Edit
As requested, for others in this situation: I edited this job by using SQL Server Management Studio. I opened a connection to my target DB then opened the "SQL Server Agent" drop-down under the connection. I opened "Jobs" and found the job i was looking for. I right-clicked on the job name and selected "Script Job As" -> "Drop and Create to" -> "New Query Window". From there I copied the relevant sections to new query windows where I modified and tested them as necessary. I then just copied and pasted the working sections back into the job window above -- COMPLETELY forgetting to double up the single quotes where necessary.
How did you add the step to the job? I wonder if a script you used escaped all of your double apostrophes and it is now trying to evaluate
WHERE ISNULL(Person.LastName, ') != ISNULL(P.LastName, ')
------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
That's "valid enough" syntax. The highlighted portion is a simple string literal, not an empty string and a comparison to another expression.

Update table column using table in another SQL Server database while using a spatial function

I would like to update a table column using a spatial function with another database table. This is what I've come up with....
UPDATE FirstDatabase.dbo.track_logs
SET county = t2.CountyName
FROM OtherDatabase.dbo.tblCounty AS t2
WHERE t2.cty_geog.STIntersects(
GEOGRAPHY::STPointFromText('Point(' + FirstDatabase.dbo.track_logs.lng + ' ' +
FirstDatabase.dbo.track_logs.lat + ')', 26915)
)
but I get this error...
An expression of non-boolean type specified in a context where a condition is expected, near ')'.
Almost there. This is one of those silly things in TSQL. You need a = 1.
That's the answer to your question, but I would also be tempted to use POINT(lat, lon, SRID) to address your comment.
UPDATE FirstDatabase.dbo.track_logs
SET county = t2.CountyName
FROM OtherDatabase.dbo.tblCounty AS t2
WHERE t2.cty_geog.STIntersects(geography::Point(FirstDatabase.dbo.track_logs.lat,
FirstDatabase.dbo.track_logs.lng,
26915)) = 1
In a language like C#, you could write something like:
bool val = true;
if (val)
// do stuff
But in TSQL, you have to write the equivalent to:
bool val = true;
if (val == true)
// do stuff
This isn't specific to SQL Spatial, of course, you'd also have to specify WHERE bitColumnName = 1 or, as your example illustrates, WHERE bitReturningFunction(args) = 1.

Resources