I do replacing
SET #data = REPLACE(#data, 'Riched20 10.0.19041}', '');
It is ok, but recently I have detected that it can be
Riched20 10.0.18362 etc
How can I replace in common case like 'Riched20 ...}'?
Can I use a regular-expression?
It should be implementation in T-SQL
If the problem is as simple as this question makes it out to be then you could, instead, find the position of the string 'Riched20' in your value, and then the position of the first } that appears after it and use STUFF to remove the text in that range.
This assumes that the value will always have a } after 'Riched20', and that if there is a } then 'Riched20' also appears. If this isn't the case you will get the value NULL.
DECLARE #data varchar(100) = 'sdjkafhbgtajl asdgasdf, Riched20 10.0.19041} dlkghbsdfl';
SET #data = STUFF(#data, CHARINDEX('Riched20',#data),CHARINDEX('}',#data,CHARINDEX('Riched20',#data)) - CHARINDEX('Riched20',#data) +1,'');
SELECT #data;
If you need "true" pattern replacement, then you are out of luck; T-SQL does not support this as the comments mention.
Related
Please help me with error 'Numeric value '' is not recognized'.
In Snowflake i am having a variable day_minus which holds a number, using this i want to return date value of current_date minus the value given in the variable.
If there is Null or empty passed in the variable i want to get current date minus 1.
For this i have written a code like below. But it throws me an error Numeric value '' is not recognized
But it throws an
set day_minus=7;
SELECT DATEADD(DAY, concat('-',nvl(nullif(try_to_number($day_minus) ,''),1)),current_date() );
Can you please correct me where i am doing mistake
you can use case statement
SELECT DATEADD(DAY, concat('-',nvl(case when $Units ='' then 1 else $Units end ,1)),current_date() );
If you use concat then the result is always going to be a string. If you want to set the "default" value to -1 then just put -1 in your code.
The try_to_* functions take a string as their input so you'd need to make your variable a string to make this work e.g.
set day_minus='7';
You don't need nullif at all. So the final version would be something like:
set day_minus='7';
DATEADD(DAY, nvl(try_to_number($day_minus),-1),current_date() );
in need to update all the rows that have sub string like this:
'forcestartpage=xx'and replace it with 'forcestartpage=18'
* there is lots of characters before and after the substring that shouldnt change
tried this, doesnt work:
update t_reminderscont
set body = REPLACE (body,'forcestartpage=__','forcestartpage=18')
thanks
You can get away with a STUFF function:
SELECT
T.body,
Replaced = STUFF(
T.Body, -- Insert in T.Body
CHARINDEX('forcestartpage=', T.Body), -- ... at the position where 'forcestartpage=' starts
LEN('forcestartpage=18'), -- ... while replacing 17 characters
'forcestartpage=18') -- ... the value forcestartpage=18
FROM
YourTable AS T
WHERE
T.body LIKE '%forcestartpage=__%' AND
T.body NOT LIKE '%forcestartpage=18%'
However this will only work for the first appearance of the forcestartpage= on each row.
I want to search for a field matching a name followed by a number of variable size (including no number), but I can't see how to use the wildcards on PATINDEX and LIKE to detect an unknown number of digits.
This is the regexp I would like to check : MYNAME[1-9]*
It has to recognize MYNAME, MYNAME5, MYNAME12, MYNAME275, ...
It shouldn't recognize ANOTHERNAME, MYNAMEXX12, MYNAME12X5, MYNAME12X
PATINDEX and LIKE don't recognize the * on the regexp to indicate a variable number of digits.
Do you know of a way to search for a pattern where a part has a variable size ?.
Thank you.
DECLARE #Test TABLE (
Field VARCHAR(32)
)
INSERT #Test( Field )
VALUES
('MYNAME'),
('MYNAME5'),
('MYNAME12'),
('MYNAME275'),
('MYNAME275TEXT')
SELECT *
FROM #Test
WHERE (
( Field = 'MYNAME'
OR Field LIKE 'MYNAME[0-9]%'
)
AND Field NOT LIKE 'MYNAME[0-9]%[^0-9]%'
)
Bit of a wild card (geddit?) guess, however, perhaps this?
SELECT *
FROM (VALUES('MYNAME'),('MYNAME5'),('MYNAME12'),('MYNAME275'),('MYNAME654A'))V(N)
WHERE V.N = 'MYNAME'
OR (V.N LIKE 'MYNAME[0-9]%'
AND V.N NOT LIKE 'MYNAME[0-9]%[^0-9]');
I have a value in informix which is like this :
value AMOUNT: <15000000.00> USD
I need to fetch 15000000.00 afrom the above.
I am using this query to fetch the data between <> as workaround
select substring (value[15,40]
from 1 for length (value[15,40]) -5 )
from tablename p where value like 'AMOUNT%';
But, this is not generic as the lenght may vary.
Please help me with a generic query for this, fetch the data between <>.
The database I am using is Informix version 9.4.
It's a diabolical problem, created by whoever chose to break one of the fundamental rules of database design: that the content of a column should be a single, indivisible value.
The best solution would be to modify the table to contain a value_descr = "AMOUNT", a value = 15000000.00, and a value_type = "USD", and ensure that the incoming data is stored in that fashion. Easier said than done, I know.
Failing that, you'll have to write a UDR that parses the string and returns the numeric portion of it. This would be feasible in SPL, but probably very slow. Something along the lines of:
CREATE PROCEDURE extract_value (inp VARCHAR(255)) RETURNING DECIMAL;
DEFINE s SMALLINT;
DEFINE l SMALLINT;
DEFINE i SMALLINT;
FOR i = 1 TO LENGTH(inp)
IF SUBSTR(inp, i, 1) = "<" THEN
LET s = i + 1;
ELIF SUBSTR(inp, i, 1) = ">" THEN
LET l = i - s - 1;
RETURN SUBSTR(inp, s, l)::DECIMAL;
END IF;
END FOR;
RETURN NULL::DECIMAL; -- could not parse out number
END PROCEDURE;
... which you would execute thus:
SELECT extract_value(p.value)
FROM tablename AS p
WHERE p.value LIKE 'AMOUNT%'
NB: that procedure compiles and produces output in my limited testing on version 11.5. There is no validation done to ensure the string between the <> parses as a number. I don't have an instance of 9.4 handy, but I haven't used any features not available in 9.4 TTBOMK.
I am trying to pass in a null value to a TSQLDataset parameter. The query has the form:
Query_text:='MERGE INTO [Table]
USING (VALUES (:A,:B)) AS Source (Source_A, Source_B)
....
WHEN MATCHED THEN
UPDATE SET A = :A
WHEN NOT MATCHED THEN
INSERT(A, B) VALUES (:A,:B);
SQL_dataset.CommandType:=ctQuery;
SQL_dataset.CommandText:=Query_text;
SQL_dataset.ParamByName('A').AsString:='A';
SQL_dataset.ParamByName('B').AsString:={ COULD BE NULL, OR A STRING };
SQL_dataset.ExecSQL;
Parameter B is nullable, but is also a foreign key. If the user enters something in this field, then B must be validated against values in another table. If it is blank then I want it to be ignored. I was passing in '', but this obviously produces a FK violation error.
I tried:
SQL_dataset.ParamByName('B').Value:=Null;
..but then I get a "dbexpress driver does not support the tdbxtypes.unknown data type" error.
I also tried:
SQL_dataset.ParamByName('B').DataType:=ftVariant;
SQL_dataset.ParamByName('B').Value:=Null;
..but then got "dbexpress driver does not support the tdbxtypes.variant data type" error.
Not sure what I am doing wrong, any help would be appreciated. I am currently drawing up a parameter list based on whether the string is populated or not, and this works well; it's just a bit clunky (in my actual query) as there are quite a few parameters to validate.
I am using Delphi XE4 and SQL server 2012.
Update:
Thanks for all the help, your suggestions were right all along, it was something else that produced that 'dbexpress driver' error. I was creating a 'flexible' parameter list in an effort to get around my problem, and this caused the exception:
Parameter_string:='';
If B<>'' then Parameter_string:='B = :B,'
Query_text:='MERGE ...'
'...'
'UPDATE SET A = :A, '+Parameter_string+' C = :C' ....
... the idea being that if B is blank then the parameter won't be 'listed' in the query.
This doesn't work, or my implementation of it doesn't work (not sure why, I'm obviously missing a step somewhere).
Anyway, the working code:
Query_text:='MERGE ...'
'...'
'UPDATE SET A = :A, B = :B, C = :C' ....
SQL_dataset.CommandType:=ctQuery;
SQL_dataset.CommandText:=Query_text;
If B<>'' then
begin
SQL_dataset.ParamByName('B').AsString:='B';
end
else
begin
SQL_dataset.ParamByName('B').DataType:=ftString;
SQL_dataset.ParamByName('B').Value:=Null;
end;
what about:
SQL_dataset.ParamByName('B').Clear;
If I recall correctly, the db-null equivalent in Delphi is Variants.Null
Usual approach would be using parameters once per query and assign the appropriate datatype.
Value may be assigned to NULL.
var
Query_text:String;
begin
Query_text:='Declare #A varchar(100) ' // or e.g. integer
+#13#10'Declare #B varchar(100)'
+#13#10'Select #A=:A'
+#13#10'Select #B=:B'
+#13#10'Update Adressen Set Vorname=#A,Strasse=#B where Name=#B';
SQL_dataset.CommandType := ctQuery;
SQL_dataset.CommandText := Query_text;
SQL_dataset.Params.ParseSQL(SQL_dataset.CommandText,true);
Showmessage(IntToStr(SQL_dataset.Params.Count));
SQL_dataset.ParamByName('B').DataType := ftString;
SQL_dataset.ParamByName('B').Value := 'MyText';
SQL_dataset.ParamByName('A').DataType := ftString; // or e.g. ftInteger
SQL_dataset.ParamByName('A').Value := NULL;
SQL_dataset.ExecSQL;
end;