My R code is not fetching data from SQL Server - 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!

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')

String conversion in sql server

In Sql server, I want to convert a string 'EN,ES,FR'to ISNULL('EN','') + ISNULL('FR','') + ISNULL('ES',''). What is the easiest way to do that. Thanks in advance.
Is this what you mean?
declare #list nvarchar(20)
set #list = 'EN,FR,ES'
print 'ISNULL(''' + replace(#list, ',', ''','''') + ISNULL(''') + ''','''')'
Output is
ISNULL('EN','') + ISNULL('FR','') + ISNULL('ES','')
...or have I got completely the wrong end of the stick?!

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.

update query with xml sql server 2008

I am having problem in updating database from xml and dynamic query.
Exec('UPDATE ' + #DbInstance + 'dbo.tblAcademic
SET tblacademic.RollNo = XMLAcademic.Item.value(''#RollNo'', ''VARCHAR(50)''),
tblacademic.Board = XMLAcademic.Item.value(''#Board'', ''VARCHAR(150)''),
tblacademic.PassingYear = XMLAcademic.Item.value(''#PassingYear'', ''VARCHAR(10)''),
tblacademic.Semester = XMLAcademic.Item.value(''#Semester'', ''VARCHAR(5)''),
tblacademic.MarksObt = XMLAcademic.Item.value(''#MarksObt'', ''varchar(9)''),
tblacademic.MaxMarks = XMLAcademic.Item.value(''#MaxMarks'', ''int'')
FROM ''' + Convert(varchar, #XMLEducationalDetail) + '''.nodes(''/root/row'') AS XMLAcademic(Item)
WHERE tblacademic.AcademicID = XMLAcademic.Item.value(''#AcademicID'', ''int'')')
This is showing error at Convert function and without convert function there is also execution error showing xml to nvarchar error.

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