I need to modify an MS SQL "job" and add a step. I am creating the step in SSMS to test what I am doing. I am on a DEV server.
I need to do a SELECT INTO to create or populate a table. The only complication is that the FROM clause references a "Linked Server" that is Oracle. The basic query is:
SELECT *
INTO MyDatabase.MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
I get two errors reported in SSMS:
No matter what I call the "new" local table SSMS reports that it is an invalid object.
I am told that there is a syntax error near FROM
In the existing DB job there are several examples of this sort of usage. I am just not sure why it is failing here.
What have I tried? I have tried the following in SSMS on my desktop and RDP'd into the DEV server as an 'admin' user to use SSMS there.
SELECT *
INTO MyDatabase.MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
--
USE MyDatabase;
SELECT *
INTO MySchema.MyTable
FROM LinkedServer..RemoteSchema.RemoteTable
--
SELECT *
INSERT INTO MyDatabase.MySchema.MyTable
FROM OPENQUERY(LinkedServer, '
select * from RemoteSchema.RemoteTable
');
--
SELECT *
INTO MyDatabase.MySchema.foo
FROM MyDatabase.MySchema.ExistingTable
In the last instance above I am making sure that the source table exists and that the target table does not. I think I am following the rules from HERE
What am I missing?
EDIT
What I was missing was a giant typo. I was actually using incorrect syntax like the third example above: select * INSERT into.... I was blind to the word "INSERT" in my SSMS query window and managed to edit it out of most of the examples above.
You should create an empty table and then insert rows from the linked server into the table.
Create table #MyTable (
col1
, col2 ...
);
INSERT INTO #MyTable (col1, col2 ...)
SELECT col1, col2
FROM LinkedServer..RemoteSchema.RemoteTable
Related
I'm trying to figure out how to create a copy of a table from one linked server to another inside Management Studio. I have both linked servers created, and I can query them. However, one is a SQL Server instance and the other is a ODBC connection to a QuickBooks QODBC connection.
When querying the SQL Server instance I run a query like this
SELECT *
FROM [MYSERVERNAME\SQLSERVICEINSTANCE].[DATABASENAME].[DBO].[TABLENAME]
When querying the QODBC QuickBooks database I run a query like this
SELECT *
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
How can I select * into SQLSERVER.Invoices FROM QUICKBOOKS.Invoices?
select * into SQLSERVER.Invoices FROM QUICKBOOKS.Invoices is actually pretty close to what you want.
insert into [DATABASENAME].[DBO].[TABLENAME]
(column1, columns2)
SELECT column1, columns2
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
Now I guess you want to do this regularly? The most straightforward way is to to run this first to clear the target table:
TRUNCATE TABLE [DATABASENAME].[DBO].[TABLENAME]
If you want to make an exact copy use this:
USE [DATABASENAME]
IF EXISTS (
SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[DBO].[TABLENAME] ')
AND type in (N'U')
)
DROP TABLE [DBO].[TABLENAME]
SELECT *
into [DBO].[TABLENAME]
FROM OPENQUERY(QUICKBOOKS, 'SELECT * FROM Invoice')
You can pop any of these scripts into a sql agent job to refresh on a regular basis
The following tSQL query is puzzling me:
select 1 as FIELD into #TEMP
drop table #TEMP
select 1 as FIELD into #TEMP
When I run it from SQL Server Management Studio session window (pressing F5 to the whole query, as a group), I get the following error:
Msg 2714, Level 16, State 1, Line 3
There is already an object named '#TEMP' in the database.
Note that table #TEMP doesn't exist before the query is executed.
I thought that the code shouldn't produce any errors as line 2 is dropping the temporary table. But it is as if the drop isn't taking effect when line 3 is executed.
My questions:
Why does the error happen?
How do I fix the query so it executes as intended?
PS. The query above is a simplification of a real world query of mine that is showing the same symptoms.
PS2. Regardless of whether this is a sound programming practice or not (as Sean hinted in his comments), this unexpected behavior prompted me to look for information on how these queries are parsed in the hopes that the knowledge will be helpful to me in the future.
As I found the seek of existing tables are different:
select 1 as FIELD into #TEMP
drop table #TEMP
When you use into statement after those commands:
select 1 as FIELD into #TEMP
Error is:
There is already an object named '#TEMP' in the database.
And When you use a select on #TEMP after those commands:
select * from #TEMP
Error is:
Invalid object name '#TEMP'.
So, In first case THERE IS an object with #TEMP name and in the other case THERE IS NOT an object with #TEMP name !.
An important note from technet.microsoft is:
DROP TABLE and CREATE TABLE should not be executed on the same table in the same batch. Otherwise an unexpected error may occur.
In notes of dropping tables by SQL Server Database Engine:
The SQL Server Database Engine defers the actual page deallocations, and their associated locks, until after a transaction commits.
So the second error on using select statement may related to the actual page deallocations and the first error on using into statement may related to duration between lock associated until the transaction commits.
Here try this:
select 1 as FIELD into #TEMP
drop table #TEMP
GO
select 1 as FIELD into #TEMP
This might be a very basic question but I can't find the correct command for it.
I can list the datafields in a table using the command
select * from cat where table_name='mytable';
How do I check the data that has been inserted in this table using sqlplus?
You can get all the data from a table by using the simple statement:
select * from <table name>;
so if you want to get all the data from the table cat, try:
select * from cat;
if you'd like to get all the data from mytable, try:
select * from mytable;
any where clause that you define in the statement is used to filter the results that this simple 'select everything from' statement would return.
connect to the desired user in which you want to see tables
SQL QUERY: select table_name from user_tables;
CREATE TABLE #names (
[name] nvarchar(max)
);
INSERT INTO #names ([name])
SELECT CustomerName from CustomerInformation
Where status=3
Will the INSERT INTO #names... show up in a SQL Server trace as an INSERT to a table in tempdb or a select from CustomerInformation. Or will both show up in the trace?
Basically, will the trace show the statement as a insert or a select?
Depends what event you're actually looking for in the Trace:
SQL:StmtCompleted and SP:StmtCompleted will show the statement that executed: INSERT INTO ... SELECT FROM ...
SQL:BatchCompleted will show the complete SQL batch (request) that executed: CREATE TABLE ...; INSERT INTO ... SELECT FROM ....
Other events enabled in the Trace will show up accordingly (locks, security audits, query plans etc etc). But the gist of your question is: INSERT INTO ... SELECT ... FROM ... is one single statement, not two statements.
Your statement will appear in the trace once, exactly as you enter it. The database associated with the statement will be the current database when the command is executed. Since you don't specify a database in the FROM clause, the current database will be the database where the CustomerInformation table resides.
I've created an ADO.NET connection manager, and a DataReader source with the following SQL Command:
select
'test' as testcol
INTO
#tmp
select * from #tmp
If I click the refresh button in the DataReader component, I get SqlException "Invalid object name #tmp". The SQL statment itself is clearly valid and executes properly in sql server management studio. I've also tried setting DelayValidation on the connection manager, to no avail.
is the error on the INSERT or the SELECT?
if you are issuing only one command that contains both the INSERT and SELECT, try putting a semicolon before the SELECT.
EDIT after OP comment
encapsulate all the logic within a stored procedure:
CREATE PROCEDURE YourProcedureName
AS
select
'test' as testcol
INTO
#tmp
select * from #tmp
GO
the have your application run this single SQL command:
exec YourProcedureName
EDIT after next OP comment
OP doesn't say which SQL Server version they are using, if 2005 or up, try a CTE:
;with CTEtemp as
(
select
'test' as testcol
)
select * from CTEtemp
Why couldn't this be replaced with a "SELECT 'test' as testcol"? The SSIS query parser may be having trouble with it because there's a temp table involved and it expects a single statement, not an actual SQL script. Or, if what you're sharing above is only an example for illustration, maybe something like this:
SELECT *
FROM (SELECT 'test' AS testcol)
Can you elaborate on what you're trying to accomplish here and, if it is, why the temp table is required?
Use sp_executesql
Your command would become
exec sp_executesql #statement=N'
select
''test'' as testcol
INTO
#tmp
select * from #tmp'
You must use nvarchar string (hence the N), and escape single quotes by doubling them.
I had the same problem as you and this is how I just fixed it.