IsNull ExecuteSql incorrect syntax error - sql-server

I'm trying to figure out how to solve 'incorrect syntax near ExecuteSql' error for the following line of code:
IsNull (ExecuteSql ('Numeric' , SELECT 1 FROM sys.tables a
INNER JOIN sys.indexes b ON a.object_id = b.object_id WHERE b.is_primary_key = 1 AND a.name = ##ObjectName AND a.schema_id = SCHEMA_ID (##SchemaName)'), 0)
and I'm at a loss.
I think I understand that where it finds a null it will return 0, but beginning the line with IsNull confuses me.
Also, the letters a and b and a.object or b.object or b.is_primary I don't understand yet.
I don't suppose anyone could walk me through what is happening here.
I cannot even find what ## refers to.

ExecuteSQL() takes two parameters, both of which need to be strings. You don't have an opening ' for your second string...
Try this, with the missing ' added back in? (Note: I didn't check anything else about your query)
SELECT
IsNull(
ExecuteSql(
'Numeric',
'SELECT 1 FROM sys.tables a
INNER JOIN sys.indexes b ON a.object_id = b.object_id
WHERE b.is_primary_key = 1
AND a.name = ##ObjectName
AND a.schema_id = SCHEMA_ID (##SchemaName)'
)
, 0
)
In terms of the letters, etc, they're standard SQL syntax...
The phrase sys.tables a means that you are using the table sys.tables but want to alias it to a from now on. That's why you see a.name later on.
The same applies to sys.indexes b, creating the alias b for table sys.indexes.
I'd consider this bad-practice in this form. It's just the same as having variable a and b in another language. Much better to have aliases/variable names that mean something in my opinion. But this does server to shorten the code.
For the ## sections are system variables explained on the msdn blog here.
##ObjectName - corresponds to the name field in sys.objects.
The variable will be replaced with the name of the current object.
##SchemaName - corresponds to the name field in sys.schemas.
The variable will be replaced with the schema for the current
object if the current object belongs to a schema.
The ExecuteSQL() function then executes the code in the second parameter, but only takes the first value of the first column, and returns it as the type in ExecuteSQL()'s first parameter. As it always returns one value, it may return NULL. ISNULL(ExecuteSQL(), 0) replaces any NULL return value with a 0.

Related

Leetcode SQL 1440. Evaluate Boolean Expression

Table Variables:
Column Name
Type
name
varchar
value
int
name is the primary key for this table.
This table contains the stored variables and their values.
Table Expressions:
Column Name
Type
left_operand
varchar
operator
enum
right_operand
varchar
(left_operand, operator, right_operand) is the primary key for this table.
This table contains a boolean expression that should be evaluated.
operator is an enum that takes one of the values ('<', '>', '=')
The values of left_operand and right_operand are guaranteed to be in the Variables table.
Write an SQL query to evaluate the boolean expressions in Expressions table.
Return the result table in any order.
I am working on a SQL problem as shown in the above. I used MS SQL server and tried
SELECT
left_operand, operator, right_operand,
IIF(
(left_values > right_values AND operator = '>') OR
(left_values < right_values AND operator = '<' ) OR
(left_values = right_values AND operator = '='), 'true', 'false') as 'value'
FROM
(SELECT *,
IIF(left_operand = 'x', (SELECT value FROM Variables WHERE name='x')
, (SELECT value FROM Variables WHERE name='y')) as left_values,
IIF(right_operand = 'x', (SELECT value FROM Variables WHERE name='x')
, (SELECT value FROM Variables WHERE name='y')) as right_values
FROM Expressions) temp;
It works well on the test set but gets wrong when I submit it.
I think my logic is correct, could anyone help take a look at it and let me know what my problem is?
Thank you!
It feels like your example code is a lot more complicated than it needs to be. That's probably why it's failing the check. In your FROM you're using sub-selects but really a simple inner join would work much simpler. Also, if there were variables other than X and Y it doesn't look like your example code would work. Here's my code that I wrote in Postgres (should work in any SQL though).
SELECT e.left_operand, l.value as left_val, e.operator, e.right_operand, r.value as right_val,
CASE e.operator
WHEN '<' THEN
(l.value < r.value)
WHEN '=' THEN
(l.value = r.value)
WHEN '>' THEN
(l.value = r.value)
END as eval
FROM
expression as e
JOIN
variable as l on e.left_operand = l.name
JOIN
variable as r on e.right_operand = r.name
Here's a screenshot of my output:
I also have a db-fiddle link for you to check out.
https://www.db-fiddle.com/f/fdnJVSUQHS9Vep4uDSe5ZP/0

Getting a warning about null values being eliminated from a SET, but there is no null value

I know what this warning means, however in this case there are definitely no null values.
The result also appears to be correct, but the warning makes me curious (and concerned) since it means there's something in play that I don't understand.
The warning is:
Warning: Null value is eliminated by an aggregate or other SET operation.
Here's the statement:
UPDATE Contacts
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM (
SELECT dbo.Contacts.ID
FROM dbo.Contacts
LEFT OUTER JOIN dbo.Order_Batches ON dbo.Order_Batches.EnteredByContactID = dbo.Contacts.ID
GROUP BY dbo.Contacts.ID
HAVING (COUNT(dbo.Order_Batches.ID) > 0)
) i
WHERE i.ID = Contacts.ID
As you can see, this is an UPDATE statement where I needed to do some join logic, and the COUNT() statement must be the problem. But if I take that nested SELECT out and run it by itself, there are no nulls in the result:
ID
37
39
52
54
79
81
I assume there's something about how this nested select works that I don't understand. I've tried looking at execution plans and pulling this apart in various ways to reveal a null value or some other problem. I've tried making tweaks to the statement to try and get a null to appear - no luck.
So, to be clear, I would like to understand why this message occurs, but only when the query is nested inside an UPDATE statement's FROM clause.
Does not need aggregation if you are ensuring that there is at least an order by the contact to update this. Use EXISTS instead.
UPDATE c
SET IsActiveCampaignClient = 1,
NeedsActiveCampaignSync = 1
FROM Contacts c
WHERE exists (
(
SELECT 1 -- making sure there is at least an order
FROM Order_Batches o
where o.EnteredByContactID = c.ID
)

Using SQL to find entries that were originally X and later changed to Y

I recently started using SQL for work and don't have much experience of it so I'm sorry if this is a ridiculous question.
I'm looking for an entry that was originally listed as X but was then later changed to Y, I figure that a nested sub query is the way to go but the one I'm trying doesn't seem to use the nested bit.
Here is the code I'm trying
SELECT *
FROM [HOME].[dba].[ARCHIVE]
where FRIE like 'AR8%'
and RESULT = 'X'
and EXISTS(SELECT FRIE, RESULT
FROM [HOME].[dba].[ARCHIVE]
where RESULT = 'Y');
Everything as far as the EXISTS works but afterwards it just ignores the nested query
Your query doesn't have the same WHERE clause in the EXISTS portion. I think this will work for you:
SELECT *
FROM [HOME].[dba].[ARCHIVE]
WHERE FRIE like 'AR8%'
AND RESULT = 'X'
AMD EXISTS(SELECT TOP 1 1
FROM [HOME].[dba].[ARCHIVE]
where FRIE like 'AR8%' AND RESULT = 'Y');
I'd recommend using an INNER JOIN to a subquery rather than using an EXISTS statement. Something like this:
SELECT *
FROM [HOME].[dba].[ARCHIVE] a
INNER JOIN (SELECT FRIE
FROM [HOME].[dba].[ARCHIVE]
WHERE RESULT = 'Y') t1 ON a.FRIE = t1.FRIE
WHERE
FRIE like 'AR8%'
and RESULT = 'X'
That would return all rows from ARCHIVE where they there is a row with the same FRIE with a RESULT of X and a RESULT of Y.
Hopefully that helps.

postgres comparing varying character with array from string_to_array

I'm having problems comparing Postgres types, and would be grateful for some help. I am extracting valid document types from a configuration table that holds a tilda-separated string, as follows:
SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds'
this gives me an array of values, so
'doc1|doc2|doc3' becomes {doc1,doc2,doc3}
Next I need to select the documents for a given person which match my document types:
SELECT * FROM people
JOIN documents ON ...
WHERE kind IN
(SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds')
the documents.kind column is 'character varying'
my understanding is that string_to_array is producing an array of text values 'text[]'
This query produces the error 'ERROR: operator does not exist: character varying = text[]'
If I cast 'kind' into text, with
SELECT * FROM people
JOIN documents ON ...
WHERE kind::text IN
(SELECT string_to_array(value,'|') as visa_document_kinds FROM languages_united.company_configs WHERE option = 'visa_document_kinds')
I get the error 'ERROR: operator does not exist: text = text[]'
I'm not sure how to compare the two, and would be grateful for any advice.
Thanks in advance
Dan
Postgres 9.4.1
You can select against any array element by using the ANY operator, if your sub-query returns exactly one row:
SELECT *
FROM people
JOIN documents ON ...
WHERE kind = ANY (
SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds');
If the sub-query possibly returns multiple rows, you can use the regexp_split_to_table() function:
SELECT *
FROM people
JOIN documents ON ...
JOIN (
SELECT document_kinds
FROM company_configs,
regexp_split_to_table(value, '\|') as document_kinds
WHERE option = 'document_kinds') sub ON sub.document_kinds = kind;
(You will have to tweak this to match the rest of your query.)

Unusual SQL Server query with "select top 1 #arastr = k"

select top 1 #arastr = k
from #m
where datalength(k) = (select max(datalength(k)) from #m)
What does this query do, and what is the point of select top 1 #arastr = k? This query is taken from a stored procedure which has been working for 7-8 years, so there is nothing wrong with the query, but I could not understand what it does.
(#m is a temp table which is created in the early part of the query.)
The query select one random value (since top is used without an order by clause) from the column k in the temporary table #m and assigns it to a variable #arastr (which has been previously declared supposedly). The string selected will be any matching the longest (measured in bytes (by the datalength function)) string in the table.
This is a quite common (but a little old fashioned) way to get the value of k into the (previously declared!) variable #arastr for later usage.
The function DATALENGTH will measure the length of e.g. a VARCHAR.
With TOP 1 you geht in any case only one result row, the one with the "longest" k, it's value is in #arastr afterwards...
EDIT: As pointed out by #jpw this will be random, if there is more than one k with the same (longest) length.
Without knowing, what #m looks like and what kind of data is in 'k' I cannot tell you any more.
probably makes more sense if it looks like this
SET #arastr = (SELECT TOP 1 k
FROM #m
WHERE DATALENGTH(k) = (SELECT MAX(DATALENGTH(k)) FROM #m))

Resources