Executing SQL from R - sql-server

I would like to execute SQL query from R and get results into dataframe. Here is my example.
library(RODBC)
db.handle <-odbcDriverConnect('driver=
{SQL Server Native Client 11.0};server=some_server\\some_server_2;
database = some_db;trusted_connection=yes')
query <-"select top 10 * into #temp_table from table_A select * from #temp_table"
res <- sqlQuery(db.handle, query)
print(res)
The above code return character(0). It works without #temp_table. Is there way to make it work with temp table?

While this may be a valid SQL statement, I'm not sure the the 'RODBC' package understands what to do with your query with the sqlQuery() command alone.
Assuming you have read and write permissions to the database you're using, try separating the functional operation into parts: sqlQuery(), sqlSave(), sqlQuery(). If you need to remove an existing temp table, you can use sqlDrop(). Don't forget to close the connection when finished.
Alternatively, you could run SQL like transformations in R with 'dplyr' after getting results from the 'select top 10 from table_A' query.

Related

ORACLE to MSSQL using SSMS Import Wizard with Query to Update Rows

I have a situation which prevent me of updating rows in a table in MSSQL getting the data from ORACLE. I can INSERT fine from ORACLE to MS SQL using a SELECT statement like:
SELECT XRECORDACTIVATIONDATE, XRECORDCUTOFFDATE, XRECORDREVIEWDATE,
XRECORDFILINGDATE, XNOLATESTREVISIONDATE, XNEWREVISIONDATE, XDATERECEIVEDDOC,
XINACTIVEDATE, DCREATEDATE, DINDATE, DRELEASEDATE, DLASTMODIFIEDDATE
FROM STELLENT.V_EXPORT_TO_MSSQL V
But when I try to update the rows based on an unique ID using:
UPDATE D
SET D.XRECORDACTIVATIONDATE = V.XRECORDACTIVATIONDATE
FROM DBO.DOCUMENT D
INNER JOIN STELLENT."V_EXPORT_TO_MSSQL" V ON D.DID = V.DID
I get the following error:
ORA-00933: SQL command not properly ended
(System.Data.OracleClient)
DBO.DOCUMENT is a MSSQL table.
STELLENT.V_EXPORT_TO_MSSQL is a View in ORACLE
I might be writing wrong the query I will appreciate some help. thank you.
Lukasz is correct - a select statement is a lot different from an insert statement.
The ORA-00933 error means your query is not formed properly. This is because in Oracle, the database expects queries to follow a certain format/standard. Typically, queries within Oracle will have a form of SELECT [columns] FROM [tables] WHERE [conditions]. This can vary - for example if you wanted to select all data from a table, that query might look like "SELECT * FROM [table];" and the WHERE clause can be omitted because you do not need to define a condition for the database to return all rows. While queries can vary in form, in general, they will follow some type of format.
You are receiving this error because your query does not conform to the expected form, and it is because you have an INNER JOIN that directly follows your FROM clause. To fix this, I would recommend creating a query that you use to select the records you want to update, and then using that select statement to form your update statement by replacing the "SELECT" with "UPDATE".
For more on SQL Standards and how to format your queries, I would recommend taking a look at Oracle documentation. https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_1001.htm#SQLRF52344

How can I query over all db of my server without looping over DB in pymssql connection

I'd like first to know how to make a query over all the databases in my server instance with pymssql (in MSSQL management studio = right click --> new query on the server thumbnail then don't need to specify the name of the db in the query - it just gives you one more column in the output which is the segment from which the record is from). Then how do you do the same as registered servers on two or multiple hosts (I have 2 hosts and I want to pass the same query do I really need to make the two connections ?)
thanks
You could use sp_foreachdb, like this:
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; EXEC update table set foo = bar'
Maybe this can help you (but - to be honest - I did not really understand what you want :-) )
SELECT * FROM sys.databases

Does MSSQL always copy tables when using Linked Server

After googling and looking into the MS documenation (http://msdn.microsoft.com/en-us/library/ms188279.aspx) on linked servers I still couldn't get a clear answer to the following question. I'm thinking about linking 2 SQL Servers so I can create a subset of data from the source DB and insert it into an output DB (with duplicate checks before inserting) but I don't know how MSSQL processes queries that use linked databases.
As far as I know following query will result in LocalServer downloading the FarAwayTable and then executing the query locally (which is killing for performance in my case):
SELECT
f.*
FROM
FarAwayServer.FarAwayDB.dbo.FarAwayTable f,
LocalServer.LocalDb.dbo.LocalTable l
WHERE
f.ID = l.ID
My question is, will MSSQL do the same for the following query or will it only download the result (executing the whole query on the FarAwayServer):
SELECT
*
FROM
FarAwayServer.FarAwayDB.dbo.FarAwayTable f
WHERE
f.ID = 1
It will still act the same (the FarAwayTable table will be downloaded and the query will be executed locally). If you want to execute the query on FarAwayServer you should use OPENQUERY:
SELECT * FROM OPENQUERY([FarAwayServer], 'SELECT * FROM FarAwayDB.dbo.FarAwayTable f WHERE f.ID = 1')

How to execute remote query by Oracle Database Link

I use Oracle Database Link to query data from SQL Server. The query is like:
select *
from tableA#DL_SqlServer a
join tableB#DL_SqlServer b
on a.ID = b.ID
tableA and tableB is large and the result is relatively small. This query executes quickly in SQL Server since indexes are built both on the two tables. But it is very slow on Oracle Database Link to SQL Server. I guess the join operation is performed on Oracle side not on SQL Server side, thus the indexes are not used. Since I just need the joined result, I prefer to perform the query entirely on SQL Server and get the small result only. I konw that using SQL Server's linked server and OPENQUERY function can achieve this goal. I wonder how to do this on Oracle Database Link. Thanks! Btw, I have no privilege to create views on SQL Sevrer.
You most likely need to use the DBMS_HS_PASSTHROUGH package. Something like
DECLARE
l_cursor PLS_INTEGER;
BEGIN
l_cursor := dbms_hs_passthrough.open_cursor#dblink_to_sql_server;
dbms_hs_passthrough.parse#dblink_to_sql_server( l_cursor, <<select statement>> );
while dbms_hs_passthrough.fetch_row#link_to_sql_server(l_cursor) > 0
loop
dbms_hs_passthrough.get_value#dblink_to_sqlserver( l_cursor, 1, <<local variable for first column>> );
dbms_hs_passthrough.get_value#dblink_to_sqlserver( l_cursor, 2, <<local variable for second column>> );
...
end loop;
dbms_hs_passthrough.close_cursor#dblink_to_sqlserver( l_cursor );
END;

SQL Server Linked Server Example Query

While in Management Studio, I am trying to run a query/do a join between two linked servers.
Is this a correct syntax using linked db servers:
select foo.id
from databaseserver1.db1.table1 foo,
databaseserver2.db1.table1 bar
where foo.name=bar.name
Basically, do you just preface the db server name to the db.table ?
The format should probably be:
<server>.<database>.<schema>.<table>
For example:
DatabaseServer1.db1.dbo.table1
Update: I know this is an old question and the answer I have is correct; however, I think any one else stumbling upon this should know a few things.
Namely, when querying against a linked server in a join situation the ENTIRE table from the linked server will likely be downloaded to the server the query is executing from in order to do the join operation. In the OP's case, both table1 from DB1 and table1 from DB2 will be transferred in their entirety to the server executing the query, presumably named DB3.
If you have large tables, this may result in an operation that takes a long time to execute. After all it is now constrained by network traffic speeds which is orders of magnitude slower than memory or even disk transfer speeds.
If possible, perform a single query against the remote server, without joining to a local table, to pull the data you need into a temp table. Then query off of that.
If that's not possible then you need to look at the various things that would cause SQL server to have to load the entire table locally. For example using GETDATE() or even certain joins. Others performance killers include not giving appropriate rights.
See http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/ for some more info.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME..TABLENAME')
This may help you.
For those having trouble with these other answers , try OPENQUERY
Example:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from [DBName].[schema].[tablename]')
If you still find issue with <server>.<database>.<schema>.<table>
Enclose server name in []
You need to specify the schema/owner (dbo by default) as part of the reference. Also, it would be preferable to use the newer (ANSI-92) join style.
select foo.id
from databaseserver1.db1.dbo.table1 foo
inner join databaseserver2.db1.dbo.table1 bar
on foo.name = bar.name
select * from [Server].[database].[schema].[tablename]
This is the correct way to call.
Be sure to verify that the servers are linked before executing the query!
To check for linked servers call:
EXEC sys.sp_linkedservers
right click on a table and click script table as select
select name from drsql01.test.dbo.employee
drslq01 is servernmae --linked serer
test is database name
dbo is schema -default schema
employee is table name
I hope it helps to understand, how to execute query for linked server
Usually direct queries should not be used in case of linked server because it heavily use temp database of SQL server. At first step data is retrieved into temp DB then filtering occur. There are many threads about this. It is better to use open OPENQUERY because it passes SQL to the source linked server and then it return filtered results e.g.
SELECT *
FROM OPENQUERY(Linked_Server_Name , 'select * from TableName where ID = 500')
For what it's worth, I found the following syntax to work the best:
SELECT * FROM [LINKED_SERVER]...[TABLE]
I couldn't get the recommendations of others to work, using the database name. Additionally, this data source has no schema.
In sql-server(local) there are two ways to query data from a linked server(remote).
Distributed query (four part notation):
Might not work with all remote servers. If your remote server is MySQL then distributed query will not work.
Filters and joins might not work efficiently. If you have a simple query with WHERE clause, sql-server(local) might first fetch entire table from the remote server and then apply the WHERE clause locally. In case of large tables this is very inefficient since a lot of data will be moved from remote to local. However this is not always the case. If the local server has access to remote server's table statistics then it might be as efficient as using openquery More details
On the positive side T-SQL syntax will work.
SELECT * FROM [SERVER_NAME].[DATABASE_NAME].[SCHEMA_NAME].[TABLE_NAME]
OPENQUERY
This is basically a pass-through. The query is fully processed on the remote server thus will make use of index or any optimization on the remote server. Effectively reducing the amount of data transferred from the remote to local sql-server.
Minor drawback of this approach is that T-SQL syntax will not work if the remote server is anything other than sql-server.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME.SCHEMA_NAME.TABLENAME')
Overall OPENQUERY seems like a much better option to use in majority of the cases.
I have done to find out the data type in the table at link_server using openquery and the results were successful.
SELECT * FROM OPENQUERY (LINKSERVERNAME, '
SELECT DATA_TYPE, COLUMN_NAME
FROM [DATABASENAME].INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME =''TABLENAME''
')
Its work for me
Following Query is work best.
Try this Query:
SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT * FROM [DATABASE_NAME].[SCHEMA].[TABLE_NAME]')
It Very helps to link MySQL to MS SQL
PostgreSQL:
You must provide a database name in the Data Source DSN.
Run Management Studio as Administrator
You must omit the DBName from the query:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from schema."tablename"')
For MariaDB (and so probably MySQL), attempting to specify the schema using the three-dot syntax did not work, resulting in the error "invalid use of schema or catalog". The following solution worked:
In SSMS, go to Server Objects > Linked Servers > Providers > MSDASQL
Ensure that "Dynamic parameter", "Level zero only", and "Allow inprocess" are all checked
You can then query any schema and table using the following syntax:
SELECT TOP 10 *
FROM LinkedServerName...[SchemaName.TableName]
Source: SELECT * FROM MySQL Linked Server using SQL Server without OpenQuery
Have you tried adding " around the first name?
like:
select foo.id
from "databaseserver1".db1.table1 foo,
"databaseserver2".db1.table1 bar
where foo.name=bar.name

Resources