Set empty value of column before create new one in case - sql-server

I have sp like this:
DECLARE #comando as varchar(5000)
set #comando = 'DTEXEC /FILE \"" /de "pass" /CHECKPOINTING OFF /REPORTING EW'
select #comando = #comando + ' /SET "\"\Package.Variables[' + Replace(str_NombreVariable,'User::','') + '].Value\"";'
+ str_ValorVariable +
CASE WHEN str_NombreVariable LIKE '%v_sRutaArchivo%' THEN #archivoCargado + '.csv\""' ELSE '' END + ''
from [Catalogo].[catVariablesEtl] where IdPaquete = 42
That I want to do is to do another case:
CASE WHEN str_NombreVariable LIKE '%v_sCadenaConexion%' THEN '"\"'+ str_ValorVariable ELSE '' END +
But I want to drop result of v_sCadenaConexion value after create this new one with case. How can I do that? Because If I use case with query it just duplicate existing value .
I want something like if str_NombreVariable exist get that value and create new one with my case sentence. How can I achieve that?
Problem:
Package.Variables[v_sCadenaConexion].Value\"";Data Source=0.0.0.0\BA;User ID=BAS;Password=000;Initial Catalog=BOS;Persist Security Info=True;Initial Catalog=SS;Persist Security Info=True;
"\"Data Source=0.0.0.0\BA;User ID=BAS;Password=000;Initial Catalog=BOS;Persist Security Info=True;Initial Catalog=SS;Persist Security Info=True;
As you can see it duplicate value. So I want to dismiss first one and keep second one(CASE one)

Not sure if this is what you mean or not...
DECLARE #comando as varchar(5000)
set #comando = 'DTEXEC /FILE \"" /de "pass" /CHECKPOINTING OFF /REPORTING EW'
select #comando = #comando + ' /SET "\"\Package.Variables[' + Replace(str_NombreVariable,'User::','') + '].Value\"";'
+ CASE WHEN str_NombreVariable LIKE '%v_sCadenaConexion%'
THEN '"\"'+ str_ValorVariable
ELSE str_ValorVariable +
CASE WHEN str_NombreVariable LIKE '%v_sRutaArchivo%'
THEN #archivoCargado + '.csv\""'
ELSE ''
END
END + ''
from [Catalogo].[catVariablesEtl] where IdPaquete = 42

Related

Correct usage of Dynamic SQL in SQL Server

I’m using static SQL for 99% of the time, but a recent scenario led me to write a dynamic SQL and I want to make sure I didn’t miss anything before this SQL is released to production.
The tables’ names are a combination of a prefix, a 2 letters variable and a suffix and column name is a prefix + 2 letters variable.
First I’ve checked that #p_param is 2 letters length and is “whitelisted”:
IF (LEN(#p_param) = 2 and (#p_param = ‘aa’ or #p_param = ‘bb’ or #p_param = ‘cc’ or #p_param = ‘dd’ or #p_param = ‘aa’)
BEGIN
set #p_table_name = 'table_' + #p_param + '_suffix';
set #sql = 'update ' + QUOTENAME(#p_table_name) + ' set column_name = 2 where id in (1,2,3,4);';
EXEC sp_executesql #sql;
--Here I’m checking the second parameter that I will create the column name with
IF (LEN(#p_column) = 2 and (#p_column = 'ce' or #p_column = 'pt')
BEGIN
Set #column_name = 'column_name_' + #p_column_param;
set #second_sql = 'update ' + QUOTENAME(#p_table_name) + ' set ' +
QUOTENAME(#column_name) + ' = 2 where id in (#p_some_param);';
EXEC sp_executesql #second_sql, N'#p_some_param NVARCHAR(200)', #p_some_param = #p_some_param;
END
END
Is this use case safe? Are there any pitfalls I should be a ware of?
Seems like you've lost some things in the translation to meaningless names to prepare your query to post here, so it's kinda hard to tell. However, the overall approach seems OK to me.
Using a whitelist with QUOTENAME for the identifiers will protect you from SQL injections using the identifiers parameters, and passing the value parameters as a parameter to sp_executeSql will protect you from SQL injections using the value parameters, so I would say you are doing fine on that front.
There are a couple of things I would change, though.
In addition to testing your tables and columns names against a hard coded white list, I would also test then against information_schema.columns, just to make sure that the procedure will not raise an error in case a table or column is missing.
Also, Your whitelist conditions can be improved - Instead of:
IF (LEN(#p_param) = 2 and (#p_param = ‘aa’ or #p_param = ‘bb’ or #p_param = ‘cc’ or #p_param = ‘dd’ or #p_param = ‘aa’)
You can simply write:
IF #p_param IN('aa', 'bb', 'cc','dd')

My R code is not fetching data from SQL Server

While the normal Select statements used on R are fetching the data, I am not able to fetch the data using SQL on the following query:
The SQL part is working on SQL Server 2008. Also, I am using RStudio
Any suggestions what is wrong here?
qf<-sqlQuery(mycon,"USE MDM_STAT
+ DECLARE #RUNMONTH INT;
+ DECLARE #RUNYEAR INT;
+ DECLARE #PERIOD INT;
+ DECLARE #FISCALRUNYEAR INT;
+ DECLARE #FISCALRUNYEAR_BEGIN INT;
+ SET #RUNMONTH=MONTH(GETDATE());
+ SET #RUNYEAR=YEAR(GETDATE());
+ SET #PERIOD=
+ CASE
+ WHEN #RUNMONTH>3 THEN (#RUNMONTH-3)
+ ELSE 9+#RUNMONTH
+ END
+ ;
+ SET #FISCALRUNYEAR=
+ CASE
+ WHEN #RUNMONTH>3 THEN #RUNYEAR
+ ELSE #RUNYEAR-1
+ END
+ ;
+ SET #FISCALRUNYEAR_BEGIN=
+ CASE
+ WHEN #PERIOD=12 THEN #FISCALRUNYEAR
+ ELSE #FISCALRUNYEAR-1
+ END
+ ;
+
+ select * from dbo.TEMP_CUST_OPERATING_PROFIT OP
+ where OP.Sales_Year=#FISCALRUNYEAR
+ AND OP.PERIOD<=#PERIOD
+ UNION
+ select * from dbo.TEMP_CUST_OPERATING_PROFIT OP
+ where OP.Sales_Year=#FISCALRUNYEAR_BEGIN
+ AND OP.PERIOD>#PERIOD")
I suggest you to follow the following steps:
1) You should make sure the the connection string is set correctly for establishing the correct connection with the database.
a quite good explanation appears here: short youtube tutorial
2) in R write:
library(RODBC)
channel = odbcConnect("The_database_name_your_are_connecting_to")
...
sqlQuery(channel ,"your query here")
close(channel)
I suggest you to start with the simplest query and after you made sure it worked,
go with a more complex query
hope it would work for you, good luck!

T-SQL: how to update a rows that require some processing?

Let's say I have a table MessagingTemplates and a column [Subject]. Text in the column is of the following format
Operations Portal - Task proposed
Operations vendor - Task rejected
Resources Portal - Late Task
All the values in that column have the above format. I'd like to write a stored procedure that will change the text to
[CompanyName] - Task proposed - [proposedDate]
[CompanyName] - Task rejected - [proposedDate]
[CompanyName] - Late Task - [proposedDate]
I'm thinking about something like
UPDATE MessagingTemplates
SET [Subject] = '[CompanyName] - ' + [Subject] + ' - [proposedDate]'
WHERE MessageName IN ('TaskProposed, TaskRejected') -- There are many more ...
Obviously, before updating I need to remove everything that comes before -
UPDATE:
It looks like I need more processing because for some row there are more than one -. In those cases, I need to retrieve only the text after the last -.
How do I do that?
If this is a one way trip you could simple preprocess Subject:
UPDATE MessagingTemplates
SET Subject = RIGHT(#subject, LEN(#subject) - CHARINDEX('-',#subject,1) + 2)
and then run the query you have:
UPDATE MessagingTemplates
SET Subject = CompanyName + Subject + ' - ' + proposedDate
WHERE MessageName IN ('TaskProposed, TaskRejected') -- There are many more
assuming the CompnayName and proposedDate are actually other field so he table
EDIT: You comment clarifies your intend so it easy to use the quoted text as above.
UPDATE MessagingTemplates
SET Subject = '[CompanyName]' + Subject + ' - [proposedDate]'
WHERE MessageName IN ('TaskProposed, TaskRejected') -- There are many more
You can of course do it all in one update.
UPDATE MessagingTemplates
SET Subject = '[CompanyName]'
+ RIGHT(#subject, LEN(#subject) - CHARINDEX('-',#subject,1) + 2)
+ ' - [proposedDate]'
WHERE MessageName IN ('TaskProposed, TaskRejected') -- There are many more
But if may have multiple ' - ' and want to key of the last you need to mix in REVERSE()
UPDATE MessagingTemplates
SET Subject = '[CompanyName]'
+ RIGHT(#subject, CHARINDEX('-',REVERSE(#subject),1) + 2)
+ ' - [proposedDate]'
WHERE MessageName IN ('TaskProposed, TaskRejected') -- There are many more
UPDATE MessagingTemplates
SET [Subject] = '[CompanyName] ' + SUBSTRING([Subject],
CHARINDEX('-', SUBJECT), 100)
+ ' - [proposedDate]'
WHERE MessageName IN ( 'TaskProposed, TaskRejected' ) -- There are many more ...

error converting varchar to numeric : SQL Server 2008

I have this SQL statement but it return : "error converting varchar to numeric"
ADOTailles.SQL.Text := 'INSERT INTO tailles (numOF, taille, quantite, prixVente) VALUES(''' + numOF.Text + ''',''' + C.Caption + ''',''' + Q.Text + ''',''' + P.Text + ''')';
ADOTailles.ExecSQL
The numeric field is prixVente;
I used this but still the same error:
ADOTailles.SQL.Text := 'INSERT INTO tailles (numOF, taille, quantite, prixVente) VALUES(''' + numOF.Text + ''',''' + C.Caption + ''',''' + Q.Text + ''',CAST(''' + P.Text + ''' AS numeric(5, 2)))');
ADOTailles.ExecSQL
NOTE: If I put an INTEGER there is no error
The full code is:
var
I: Int8;
C: TCheckBox;
Q, P: TEdit;
for I := 1 to 16 do Begin
C := FindComponent('T' + IntToStr(I)) as TCheckBox;
Q := FindComponent('Q' + IntToStr(I)) as TEdit;
P := FindComponent('P' + IntToStr(I)) as TEdit;
if C.Checked = True then begin
ADOTailles.SQL.Text := 'INSERT INTO tailles (numOF, taille, quantite, prixVente) VALUES(''' + numOF.Text + ''',''' + C.Caption + ''',''' + Q.Text + ''',''' + P.Text + ''')';
ADOTailles.ExecSQL
end;
End;
there is no SQL injection because I use this code:
StringReplace(aricleFilter.Text, '''', '', [rfReplaceAll]);
Don't create a SQL query by appending text; use parameters.
Or you'll fall into the Bobby Tables SQL injection trap.
It makes it way easier to get rid of these errors too.
Maybe your string contains not numeric symbols or incorrect decimal separator (for example "," instead of ".").
You are putting the value for the price between quotes
... ''',''' + P.Text + ''')';
This is what causes SQLServer to try a conversion from varchar to a number. To prevent that, you will have to leave of the quotes:
... ''',' + P.Text + ')';
and make sure that P.Text contains the decimal and thousands separators that SQL Server expects. Preferably only the decimal separator. You can always do the conversion yourself using StrToFloat or StrToFloatDef with P.Text as the input and then reformat that for SQLServer.
From what I can remember, SQL Server expects the US separators in SQL statements, which means you need to use a point as the decimal separator.

Toad and SQL Server 2005

where a.system_nr =''''5300'''' and
a.external_status_cd = '''''''' and
a.cust_acct_id = b.rel_cust_acct_id and
b.cust_acct_id = c.cust_acct_id and
c.cust_acct_id = d.cust_acct_id and
d.acct_status_cd = ''''OPEN'''' and
d.time_mnth_gen_id =''''' + #BegDate + ''''' and
a.cust_acct_id = e.cust_acct_id and
e.tran_dt >=''''' + #BegDate + ''''' and
e.tran_dt<=''''' + #EndDate + ''''' and
d.portfolio_cd = ''''HEQ'''' and
a.time_mnth_gen_id =''''' + #BegDate + ''''' '')'
Here is the where condition which is already written and I need to make changes.
Can you please tell me why they are using '''''+#begdate'''''? Can i use '+Bedate'?
I mean why they are using ''''' each side?
Try this in SQL Server:
select '''''someval'''''
You notice that item gives:
''someval''
In SQL Server '' will equate to a single quote character, so the above line is
select [open string][single quote][single quote]someval[single quote][single quote][close string]
Without seeing the rest of the SQL, my guesses would be:
for use in dynamic SQL as #BegDate is a variable and you have the statement ending with a single quote
the data contains a bunch of single quotes
You should not be able to just '+BegDate' because it's a variable and stripping the # would cause it to be evaluated as a field.
If you meant to just reduce the number of single quotes, I would imagine the original author put them there for a reason. You can run the query with the original single quotes and again with the reduced single quotes and see if you get the same result set.

Resources