I'm new to Redshift and I stumbled across a scenario wherein my procedure, I wanted to split a string and iterate it through and do some manipulations in it. I know redshift doesn't support arrays and I want to know how to achieve this in redshift
CREATE OR REPLACE PROCEDURE example(value IN varchar) AS $$
BEGIN
--value = 'FIRST, SECOND, THIRD' -> I want to split the string using a comma and iterate through one by one and do some manipulations.
END;
$$ LANGUAGE plpgsql;
Can Someone guide me through it?
Thanks in Advance,
You could create a loop of incrementing values, and call SPLIT_PART(), passing in the loop value.
If part is larger than the number of string portions, SPLIT_PART returns an empty string.
Therefore, you would stop the loop if an empty string is returned.
Related
I faced with strange behavior of postgresql, please, could you clarify it for me?
I created function, which return constants from constants table.
CREATE TABLE constants ( key varchar PRIMARY KEY , value varchar );
CREATE OR REPLACE FUNCTION get_constant(_key varchar) RETURNS varchar
AS $$ SELECT value FROM constants WHERE key = _key; $$ LANGUAGE sql
IMMUTABLE;
Then I added a constant to the table.
insert into constants(key, value)
values('const', '1')
;
Then if I change the value of the constant and call the function:
select get_constant('const');
Then result is CORRECT.
BUT!
If I call function in other procedure, for example:
create or REPLACE PROCEDURE etl.test()
LANGUAGE plpgsql
AS $$
declare
begin
raise notice '%', etl.get_constant('const');
END $$;
Then it rememer first result of calling, and don't change result of raise notice, even if I change constant in table.
But if I recompile procedure - then new const-value printing correct.
I tried to find documentation about it, tried google: 'cache results of postgre SQL procedure', and ect., but found nothing.
Could you clarify it and attach link to documentation this issue?
The documentation for CREATE TABLE says this about the IMMUTABLE keyword:
IMMUTABLE indicates that the function cannot modify the database and always returns the same result when given the same argument values; that is, it does not do database lookups or otherwise use information not directly present in its argument list. If this option is given, any call of the function with all-constant arguments can be immediately replaced with the function value.
So by declaring etl.get_constant with that keyword, you're telling Postgres "the output of this function will always be the same for a given input, forever".
The call etl.get_constant('const') has "all-constant arguments" - the value 'const' won't ever change. Since you've told Postgres that etl.get_constant will always return the same output for the same input, it immediately replaces the function call with the result.
So when you call etl.test() it doesn't run etl.get_constant at all, it just returns the value it got earlier, which you told it would be valid forever.
Compare that with the next paragraph on the same page (emphasis mine):
STABLE indicates that the function cannot modify the database, and that within a single table scan it will consistently return the same result for the same argument values, but that its result could change across SQL statements. This is the appropriate selection for functions whose results depend on database lookups, parameter variables (such as the current time zone), etc.
So if your "constant" is subject to change, but not within the scope of a particular query, you should mark it STABLE, not IMMUTABLE.
how would I implement custom functions in SQL?
Let's say I have a list of values and I want to transform those in a way where SQL doesn't supply a default function. E.g. look at every field's string, count the number of chars and add the sum of it to the end of each string.
In a programming language this is easy, e.g. save the field's string in a variable A, loop through the string char by char and increasing a counter by one each time, adding the counter to variable A.
But how would I do this in SQL? Can I implement EVERY function solely with the means of SQL, or do I need to use a common programming language like Java, or something like PL/SQL for that?
Thanks so much.
Let's say I have a string in one cell that is like this:
{IR1} {IR2} some text {IR3} some more text {IR6} {IR7}
I want to replace all {IR1} to {IR7} with known values from another table.
What is the most efficient way of replacing all IRX substrings with knows replacements values?
At the moment I can replace replace the number of replace values in that table: like Replace(Replace(Replace.......)...)...)..), however I want to know if there is anything better than this.
I have a query that is returning data from a database. In a single field there is a rather long text comment with a segment, which is clearly defined with marking tags like !markerstart! and !markerend!. I would like to have a query return with the string segment between the two markers removed (and the markers removed too).
I would normally do this client-side after I get the data back, however, the problem is that the query is an INSERT query that gets it's data from a SELECT statement. I don't want the text segment to be stored in the archival/reporting table (working with an OLTP application here), so I need to find a way to get the SELECT statement to return exactly what is to be inserted, which, in this case, means getting the SELECT statement to strip out the unwanted phrase instead of doing it in post-processing client-side.
My only thought is to use some convoluted combination of SUBSTRING, CHARINDEX, and CONCAT, but I'm hoping there is a better way, but, based on this, I don't see how. Anyone have ideas?
Sample:
This is a long string of text in some field in a database that has a segment that needs to be removed. !markerstart! This is the segment that is to be removed. It's length is unknown and variable. !markerend! The part of this field that appears after the marker should remain.
Result:
This is a long string of text in some field in a database that has a segment that needs to be removed. The part of this field that appears after the marker should remain.
SOLUTION USING STUFF:
I really don't like how verbose this is, but I can put it in a function if I really need to. It isn't ideal, but it is easier and faster than a CLR routine.
SELECT STUFF(CAST(Description AS varchar(MAX)), CHARINDEX('!markerstart!', Description), CHARINDEX('!markerend!', Description) + 11 - CHARINDEX('!markerstart!', Description), '') AS Description
FROM MyTable
You may want to consider implementing a CLR user-defined function that returns the parsed data.
The following link demonstrates how to use a CLR UDF RegEx function for pattern matching and data extraction.
http://msdn.microsoft.com/en-us/magazine/cc163473.aspx
Regards,
You can use Stuff function or Replace function and replace your unwanted symbols with ''.
STUFF('EXP',START_POS,'NUMBER_OF_CHARS','REPLACE_EXP')
I want to pass an integer array from input parameters of my postgresql function into sql IN clause.
Into what and how I can convert such array?
I had same problem lately.
Look here:
http://postgresql.1045698.n5.nabble.com/Using-PL-pgSQL-text-argument-in-IN-INT-INT-clause-re-post-td3235644.html
Hope it helps.
Here is a sample function:
CREATE OR REPLACE FUNCTION "GetSetOfObjects"(ids text)
RETURNS SETOF record AS
$BODY$select *
from objects
where id = any(string_to_array($1,',')::integer[]);$BODY$
LANGUAGE sql IMMUTABLE
Basically you can't. What you can do is pass in a comma-delimited list and split it apart in your function. Here are some examples using SQL Server, but I'm sure they can be translated.
Unless this (PostgreSQL) is what you're talking about.
i usually use implicit conversion
select '{1,2,3,4,5}' :: integer[]