Modified User Input value in Snowflake - snowflake-cloud-data-platform

I have a requirement to read the string passed by the user and later modify the string to get a required format and pass it as a where condition to the view.
Example
the user inputs a list of material numbers separated by commas '12345,78990,456789'. this string has to be modified to
MATCH("BOM_PATH",'12345') OR MATCH("BOM_PATH",'78990') OR MATCH("BOM_PATH",'456789')
So basically I need to separate all materials from the input string and search for those individual materials in a field called BOM_PATH which holds the value like '12345:098765:784526'
I tried using Snowflake SQL UDTF but it doesn't support variables or multiple SQL statements and Snowflake view doesn't support parameters.
So please suggest me a way on how to implement this in Snowflake.

You can do it by using ARRAY_CONTAINS() function with the input converted to the array by STRTOK_TO_ARRAY().
create or replace table bom_table(BOM_PATH varchar);
insert into bom_table (BOM_PATH)
values
('12345'),
('55555'),
('77778'),
('78990');
select * from bom_table
where
ARRAY_CONTAINS(BOM_PATH::variant,STRTOK_TO_ARRAY('12345,78990,456789',','));
Alternatively, if your BAM_PACH is a delimited list too - use ARRAY_INTERSECTION() and ARRAYS_OVERLAP()
insert into bom_table (BOM_PATH)
values
('12345:098765:784526'),
('12346:098766:784527'),
('12345:098765:777777'),
('12399:098765:777773');
select ARRAY_INTERSECTION(STRTOK_TO_ARRAY(BOM_PATH,':'),STRTOK_TO_ARRAY('12345,78990,456789',',')) from bom_table
where ARRAYS_OVERLAP(STRTOK_TO_ARRAY(BOM_PATH,':'),STRTOK_TO_ARRAY('12345,78990,456789',','));

Related

Snowflake:Export data in multiple delimiter format

Requirement:
Need the file to be exported as below format, where gender, age, and interest are columns and value after : is data for that column. Can this be achieved while using Snowflake, if not is it possible to export data using Python
User1234^gender:male;age:18-24;interest:fishing
User2345^gender:female
User3456^age:35-44
User4567^gender:male;interest:fishing,boating
EDIT 1: Solution as given by #demircioglu
It displays as NULL values instead of other column values
Below the EMPLOYEES table data
When I ran below query
SELECT 'EMP_ID'||EMP_ID||'^'||'FIRST_NAME'||':'||FIRST_NAME||';'||'LAST_NAME'||':'||LAST_NAME FROM tempdw.EMPLOYEES ;
Create your SQL with the desired format and write it to a file
COPY INTO #~/stage_data
FROM
(
SELECT 'User'||User||'^'||'gender'||':'||gender||';'||'age'||':'||age||';'||'interest'||':'||interest FROM table
)
file_format = (TYPE=CSV compression='gzip')
File format here is not important because each line will be treated as a field because of your delimiter requirements
Edit:
CONCAT function (aliased with ||) returns NULL if you have a NULL value.
In order to eliminate NULLs you can use NVL2 function
So your SQL will have series of NVL2s
NVL2 checks the first parameter and if it's not NULL returns first expression, if it's NULL returns second expression
So for User column
'User'||User||'^' will turn into
NVL2(User,'User','')||NVL2(User,User,'')||NVL2(User,'^','')
P.S. I am leaving up to you to create the rest of the SQL, because Stackoverflow's function is to help find the solution, not spoon feed the solution.
No, I do not believe multiple delimiters like this are supported in Snowflake at this time. Multiple byte and multiple character delimiters are supported, but they will need to be specified as the same delimiter repeated for either record or line.
Yes, it may be possible to do some post-processing or use Python scripts to achieve this. Or even SQL transformative statements. This is not really my area of expertise so if someone has an example for you, I'll let them add to the discussion.

How to display a multi-valued parameter onto a SSRS report in a specific way, separated in ranges and/or commas

In SSRS I need to display a multi-valued parameter onto the report in such a way that if values are chosen in sequence they appear as: 1-5, 7, 9-10, 15 and so on. And I have the following values in my drop down list of values: from '0' to '200'.
Thanks in advance for your help.
This is what I have done in SQL so far, so I am thinking to update 'String_To_Use' column so it would display: 0000-1020, 1199-1210, 1260, 1299. Then use this string to display onto the SSRS report. These are the values chosen in SSRS from the drop down box. I don't know yet how I would pass these values to the SQL code yet. Please help with this part as well.
This is the #tempTable1...column 'DPRTMNT' has the values chosen ...Checking_Dept has the value-2 when values in ranges
This is the #tempTable2..I need to update 'String_To_Use' column so it would contain: 0000-1020, 1199-1210, 1260, 1299. #tempTable1 can help to build the logic
replace dsBranchPlant with name of your data set that your using to supply data parameter. And "All" condition is if all params are choosen instead of showing each one. Game this up as an expression and see where you stand.
iif(Parameters!BranchPlant.Count = CountRows("dsBranchPlant"),"ALL",Join(Parameters!BranchPlant.Label,","))

Possible to replace digits in T-SQL

SQL Server 2008 (but have access to higher versions too)
I'm getting a string from another database on the same server. Using the below code i get some data and replace the content
INSERT INTO [DestinationDatabase].[DBO].[Table](ID, XML)
(SELECT ID, REPLACE(XML,'ReferenceID="1234"','PropertyID="2468"')
FROM [SourceDatabase].[DBO].[Customers]
This works as expected but every record has a different ReferenceID so is there a way to remove the current ReferenceID value as in the 4 digits (theres around 1000 records with different values) and replace it with another 4 digit value?
I will get the replacement value from another procedure but at this stage i need to know if it possible to find and strip the 4 digits and replace them.
If you want to use the replace function you can do it like that
REPLACE(XML,'ReferenceID="'+cast(table.field as nvarchar)+'"','ReferenceID="2468"')
REPLACE(XML,'ReferenceID="'+cast(table.field as nvarchar)+'"','ReferenceID="'+cast(table.another_field as nvarchar)+'"')
You can use xml function to do so but it seems like your XML column is not xml data type. is that correct.

Is it possible to create a parameter query in openoffice base?

In access it is very easy to use it:
BETWEEN [minimum] AND [maximum]
But what is the syntax in openoffice base?
There are two ways to do this. First is to have the query ask for user input. Colons are used to indicate user-input parameters, like this:
BETWEEN :MINIMUM AND :MAXIMUM
Second is to use a one-row filter table. Tie the user's form to this one row by making the form source something like SELECT * FROM "Filter" WHERE "FilterID" = 1. Then the user will enter the dates into the filter table, and the query will have a join to the filter table to determine the dates.

How can I dynamically select a list of several columns from a MSSQL table, without concatanating Strings?

I have taken some search but ether the examples only use one parameter / columnname or they just add Strings together.
I have a table describing projets. There are unchangable columns like an id, projectnumber and such, and several 'dynamic' columns, which a user / admin can add through an interface in the application.
After that a user should see a List of all 'dynamic' Colums, and can decide to display them through checkboxes.
So what I need now, is a query as this
SELECT id, projectname, <LIST_OF_COLUM_NAMES> FROM project
I would like this to be safe from malicious Queries, like someone very clever naming a column
; DELETE TABLE projets --
and then displaying it.
I found several solutions where the querystring is just concatenated ether on the programm side or inside a stored procedure.
I found several examples for stored procedures which get one colum name and create a query statement from it.
I found this article
How to pass an array into a SQL Server stored procedure
on which I must admit I am not sure if it applies to my problem.
Is there a way to achive this without creating a security risk throug SQL-Injection?
There are several easy way to resolve this without risk of sql injection.
Write SELECT * FROM query and limit number of columns that are seen on application, this way all columns are returned and it is up to application to decide which ones to display.
Instead of passing string of columns to stored procedure, have user pass list of column indexes and based on integer value, you can have dynamic sql that generates SELECT statement only with columns that user wants back.
If you just want to display list of columns that exists in a table to the user you should select list of columns from Information Schema Views, this way you are sure which column exists in database.
In SQL-Server you can assign parameter datatype of sysname which has is how all system objects names are stored as, this could give you extra data validation.
No matter what you decide to do, you should never concatenate strings in application or stored procedures.
I tried to work with the Information Schema Views but I was not able to avoid conatenating Strings alltogether. This is what I came up with:
When the user wants to add a Column he can enter a display name, and select from a range of Datatypes. Then I create an internal unique internal column name (like DATETIME_67).
Then I create my query like this:
String querystring = "ALTER TABLE projects ADD " + internalname + " " + typestring;
Note that the String internalname and typestring are both generated inside my code, with no input from the user (so this should be safe against injection, I guess).
Then I write the internal name and the display name to a lookup table:
String querystring = "INSERT INTO lookup (tablename, displayname) " +
"VALUES (#tablename, #displayname)";
using (SQLCommand command = new SQLCommand(querystring, con)) { //con is a SQLConnection object
command.Parameters.AddWithValue("#tablename", internalname);
command.Parameters.AddWithValue("#displayname", displayname);
}
Here the actual Input from the user is inserted, but it is parameterized, so it should also be safe.
When I retrieve the columns I want to display I do also use the (hopefully) safe internal names:
List<String> selectedColumns; //the list of internal col names
String query = "SELECT id, projectnumber, projectname {0} FROM projects"; //projectnumer and name a mandatory fields
if (selectedColumns.Count > 0)
{
fieldstring = String.Join(",", selectedColumns);
fieldstring = ", " + fieldstring;
}
query = String.Format(query, fieldstring);
Please comment on this. Is is working exactly as I need it. The user can add (and remove) custom field to the datatabe and provide display names for them. He can also define, which of the present custom field are to be displayed, and he can enter data for the created fields. I am just not sure, if this save against malicious injections.

Resources