Executing SQL statements using variables in Snowflake - snowflake-cloud-data-platform

SQL statement : "select case when 1=1 then 1 else 2 end"
The above SQL statement need to be executed using variables as we have multiple statements like the above in a single table.
Row Column_name
case when 1=1 then 1 else 2 end
case when 3=3 then 3 else 6 end
Can I do the above requirement without using javascript in Snowflake? If yes, how?
We are expecting to the output of the case statement not the string.
We have hundreds of merge statements inserted into a table. We want to execute them dynamically.

Related

Stored procedure CASE statement in WHERE clause taking parameter from Reporting Services

I am using a stored procedure and SSRS.
My data has a column that has a binary value (1=Inside/2=Outside). And in the report the user has the parameter option to select Inside (1), Outside (2), or Both (3). In the where clause I used the following CASE statement, which works great for when inside or outside is selected but returns no data when both is selected.
WHERE
db.Location = CASE
WHEN #loc = 1 THEN 1
ELSE CASE
WHEN #loc = 2 THEN 2
END
END
What can I use to be able to do the same as above, but add the ability to select both?
Why not use a simple OR?
WHERE (db.Location = #loc OR #loc = 3)
Note that you may find you want to add OPTION (RECOMPILE) to your query with such a clause, as the plans for when #loc has a value of 3 may be different to if it has 1 or 2.

How to compare the count of each table in two different databases?

I have two databases: db1 and db2 (db2 was completely empty). I was copying all the db1 to db2 but the progress was interrupted and I need to know which tables are still left to copy. How can I compare the count of each table in these two databases to know which tables I still have to transfer?
Basically, you need to loop through the data dictionary and generate some dynamic SQL which executes a count for each table.
I have assumed you're only transferring one schema. If that's not true, or you're not connecting as the target schema, you'll need to use ALL_TABLES instead of USER_TABLES, and include the OWNER column in the driving query and the dynamic query too.
declare
n pls_integer;
stmt varchar2(32767);
begin
for r in ( select table_name from user_tables order by table_name ) loop
stmt := 'select count(*) from ' || r.table_name;
-- uncomment the next line to debug errors
-- dbms_output.put_line(stmt);
execute immediate stmt into n;
-- you may wish to only display empty tables
-- if n = 0 then
dbms_output.put_line(r.table_name || ' = ' || lpad(n, 10));
-- end if;
end loop;
end;
One would hope that your data copying process was clever enough to commit only completed tables. If so you only need to run this on DB2. Otherwise on both.

Using sys.dm_os_sys_info for SQL 2008 R2 and above

I'm trying to write a query to gather memory stats across my multiple SQL editions that are SQL 2008 R2, SQL 2012, SQL 2014, SQL 2016.
Due to the column name changes in sys.dm_os_sys_info I'm trying to get around that, but both of the queries fail with:
Msg 207, Level 16, State 1, Line 7
Invalid column name 'physical_memory_kb'.
Any ideas?
IF (LEFT(cast(serverproperty('productVersion') as varchar(100)),2) = '10')
BEGIN
select physical_memory_in_bytes/1048576 FROM sys.dm_os_sys_info
END
ELSE
BEGIN
select physical_memory_kb/1024 FROM sys.dm_os_sys_info
END
select
CASE LEFT(cast(serverproperty('productVersion') as varchar(100)),2)
WHEN 10 Then physical_memory_in_bytes/1048576
ELSE physical_memory_kb/1024
END
FROM sys.dm_os_sys_info
The error you've got is compilation error, i.e. parser tries to figure out the columns of existing tables/views and it doesn't consider execution flow (IF)
You can use this code for your purpose:
IF (LEFT(cast(serverproperty('productVersion') as varchar(100)),2) = '10')
BEGIN
exec('select physical_memory_in_bytes/1048576 FROM sys.dm_os_sys_info')
END
ELSE
BEGIN
exec ('select physical_memory_kb/1024 FROM sys.dm_os_sys_info')
END
You can't put a conditional statement to select from non-existent columns like that, the compiler will still validate all the statements within the select clause.
The first conditional works because it is two distinct select statements.
I would suggest using the first conditional only, if you need additional info then select the physical_memory_in... column into a temp table or table variable and then join that into your main query.

Run Select statement in Stored Procedure based on conditional logic

I've recently been simplifying many formally manual processes on SQL Server 2008 into stored procedures. I'm attempting to turn the below multi-step process into a stored procedure with conditional logic, but not sure how to accomplish this.
Run SELECT COUNT(*) FROM vw_GENERIC_VIEW_NAME
Run SELECT COUNT(*) FROM tbl_SIMPLE_TABLE_NAME
Compare results and if they are not equal run a SELECT statement against tbl_SIMPLE_TABLE_NAME to analyze details.
Is there a way to compare the results through some sort of conditional logic and only run the final SELECT statement if they are not equal in a stored procedure on SQL Server?
Use IF statement with <> operator
IF (SELECT COUNT(*) FROM vw_GENERIC_VIEW_NAME) <> (SELECT COUNT(*) FROM tbl_SIMPLE_TABLE_NAME)
BEGIN
Select ... From tbl_SIMPLE_TABLE_NAME
END
You can just compare the counts from the 2 tables in an IF statement and conditionally execute code within the block if the valued don't match:
IF ( SELECT COUNT(*)
FROM vw_GENERIC_VIEW_NAME
) != ( SELECT COUNT(*)
FROM tbl_SIMPLE_TABLE_NAME
)
BEGIN
PRINT 'NOT EQUAL - run your code in place of this print statement'
END

Short circuit in IF clause

I have searched and found nothing about it (I believe it is impossible to do it). My problem is that I have to check if a temporary table exists and also if there is some specific data on that temporary table.
Did anyone faced this before? How did you managed to solve it? I would like to avoid creating milions of IF..ELSE blocks.
EDIT:
IF (OBJECT_ID('tempdb..#tempTable') IS NOT NULL
AND EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value'))
BEGIN
PRINT 'Temp table and data exists'
END
ELSE
BEGIN
PRINT 'Temp table or data does not exist'
END
This is what I want to do. The problem comes when the tempTable doesn't exist (that could happen). It throws an error because, although the first stamement returns false, it continues to execute the second statement. And the SELECT statement is not able to find the table and therefore throws the error. The solution I found was to do this:
IF OBJECT_ID('#tempTable') IS NOT NULL
BEGIN
IF EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value'
BEGIN
PRINT 'Temp table and data exists'
END
ELSE
BEGIN
PRINT 'Temp table exists but data does not exist'
END
END
ELSE
BEGIN
PRINT 'Temp table does not exist'
END
My question would be, is there a way of having 2 conditions and if the first condition returns false not check the second one? Kind of using && in a programming language.
What you are trying to do is not possible as this is a compile time failure and the whole statement needs to be compiled together.
It won't evaluate the first part of the statement then compile the second part only if that is true. You need to split the test for existence and the query referencing the table into two separate statements so they are compiled separately.
See here
There is no such thing as XAND logical gate (exclusive AND). In theory XAND would mean, that both operands are true or both are false. So this means XAND is the same as Equals (=), at least for bitwise logical operations.
Please show some sample code to illustrade what you are trying to do.
Regards
I have searched this sometime ago and if I remember correctly Sql Server does indeed short circuit logical conditions but it is it who decides which one it will check first regardless of the order in which they appear in the if clause.
This is probably a sketchy solution, but I sometimes use COALESCE statements to control the sorts of if, else, then structure you are trying to get at. In this case, it is a little more dirty looking because we are looking for the inverse of a coalesce statement.
DECLARE #temp_message AS varchar(100)
SELECT #temp_message = COALESCE(CASE
WHEN OBJECT_ID('tempdb..#tempTable') IS NOT NULL THEN NULL
ELSE 'Temp table does not exist'
END,
CASE
WHEN EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value') THEN NULL
ELSE 'Specified value does not exist in temp table'
END,
'Temp table and data exists')
PRINT #temp_message
The COALESCE runs one statement after another until one does not yield a NULL value. That means you can do cool things like run a series of small queries to check some values before running a large costly query. Let me know if that is really illegitimate! It worked on my machine :)
I see two ways to get close to this in MSSQL:
First. If you use sp_executesql (dynamic sql) your stored procedure will be compiled without errors. Also if #tempTable doesn't exists server will output error but continue batch execution:
exec sp_executesql N'SELECT count(*) FROM #tempTable WHERE THIS_COLUMN = ''value'''
if ##rowcount > 0
print 'ok'
else
print 'error'
end;
Second. Just create User defined function with nested IF and EXISTS (as you do it now) which output 0 and 1. And use dynamic sql to input table name and possible filter value(s) to this UDF. In this case you can use this UDF in IF.

Resources