I am trying to create a trigger using linked database to my Oracle Database. If I do select statement, it works that means my Linked Server is working perfectly but when I try to create trigger with it i get this error:
The object name 'TESTS..TESTSMS.YELL_CAT' contains more than the
maximum number of prefixes. The maximum is 2.
See my query below.
CREATE TRIGGER Insert_Into_TempYellCat ON TESTS..TESTSMS.YELL_CAT
after INSERT AS
BEGIN
INSERT INTO
TempYellCat
(
TRA_DATE,
TRA_SEQ1,
TRA_SEQ2
)
SELECT
TRA_DATE,
TRA_SEQ1,
TRA_SEQ2
FROM
TESTS..TESTSMS.YELL_CAT
END
Please I need someone to assist.
This is a dupe question. Here is the solution on SO 2 years ago.
The object name contains more than the maximum number of prefixes. The maximum is 3
Specify your schema name SQL05.ManufacturingPortal.dbo.[OPC.WriteRequests] and object name with square brackets
Related
I have a stored procedure that relies on a query to a linked server.
This stored procedure is roughly structured as follows:
-- Create local table var to stop query from needing round trips to linked server
DECLARE #duplicates TABLE (eid NVARCHAR(6))
INSERT INTO #duplicates(eid)
SELECT eid FROM [linked_server].[linked_database].[dbo].[linked_table]
WHERE es = 'String'
-- Update on my server using data from linked server
UPDATE [my_server].[my_database].[dbo].[my_table]
-- Many things, including
[status] = CASE
WHEN
eid IN (
SELECT eid FROM #duplicates
)
THEN 'String'
ELSE es
END
FROM [my_server].[another_database].[dbo].[view]
-- This view obscures sensitive information and shows only the data that I have permission to see
-- Many other things
The query itself is much more complex, but the key idea is building this temporary table from a linked server (because it takes the query 5 minutes to run if I don't, versus 3 seconds if I do).
I've recently had an issue where I ended up with updates to my table that failed to get checked against the linked server for duplicate information.
The logical chain of events is this:
Get all of the data from the original view
The original view contains maybe 3000 records, of which maybe 30 are
duplicates of the entity in question, but with 1 field having a
different value.
I then have to grab data from a different server to know which of
the duplicates is the correct one.
When the stored procedure runs, it updates each record.
ERROR STEP - when the stored procedure hits a duplicate record, it
updates my_table again - so es gets changed multiple times in a row.
The temp table was added after the fact when we realized incorrect es values were being introduced to my_table.
'my_database` does not contain the data needed to determine which is the correct tuple, hence the requirement for the linked server.
As far as I can tell, we had a temporary network interruption or a connection timeout that stopped my_server from getting the response back from linked_server, and it just passed an empty table to the rest of the procedure.
So, my question is - how can I guard against this happening?
I can't just check if the table is empty, because it could legitimately be empty. I need to definitively know if that initial SELECT from linked_server failed, if it timed out, or if it intentionally returned nothing.
without knowing the definition of the table you're querying you could get into an issue where your data is to long and you get a truncation error on your table.
Better make sure and substring it...
DECLARE #duplicates TABLE (eid NVARCHAR(6))
INSERT INTO #duplicates(eid)
SELECT SUBSTRING(eid,1,6) FROM [linked_server].[linked_database].[dbo].[linked_table]
WHERE es = 'String'
-- Update on my server using data from linked server
UPDATE [my_server].[my_database].[dbo].[my_table]
-- Many things, including
[status] = CASE
WHEN
eid IN (
SELECT eid FROM #duplicates
)
THEN 'String'
ELSE es
END
FROM [my_server].[another_database].[dbo].[view]
I had a similar problem where I needed to move data between servers, could not use a network connection so I ended up doing BCP out and BCP in. This is fast, clean and takes away the complexity of user authentication, drivers, trust domains. also it's repeatable and can be used for incremental loading.
This question already has answers here:
SQL Query to add a new column after an existing column in SQL Server 2005
(7 answers)
Closed 7 years ago.
I am still finding my feet in SQL Server, and I am trying to do a simple column addition and it is throwing an error. I am trying to add the KinAdr3 column after the KinAdr2 column but it is throwing the following error
Msg 102, Level 15, State 1, Line 5
Incorrect syntax near 'AFTER'.
Below is the SQL statement I am trying to execute
ALTER TABLE TBL_MEDICAL_Patient
ADD KinAdr3 nVARCHAR(50)
AFTER KinAdr2
Thanks in advance
The reason is simple as the above syntax is valid in MySQL but is not valid in SQL Server. In SQL Server following syntax is valid:
ALTER TABLE tablename ADD columnname INT
However, a user wanted to add the column between two of the columns. SQL Server is relational engine. The order of the column should not matter in any of the T-SQL operations. It does not matter in most of the cases (except when the table is extra large, and it has many NULL columns it impacts the size of the table). In reality whenever user wants to add a column to the table, he/she should just the column and later retrieve the column in a specific order in the table using column names.
It is always a good idea to specify the name of the column in the T-SQL query (using * is indeed a bad idea but that is out of scope of this blog post).
For more details please see the SQL SERVER – How to Add Column at Specific Location in Table
I am trying to query between two servers which have identical tables (used the same create statement for both). When I try to insert the results from Server A to Server B I get an error indicating "Column name or number of supplied values does not match table definition."
Query run on server A
Insert into ServerB.Database1.dbo.Table1
Select *
from Table1
The error is clear, but what isn't clear is the reason that it is generated. The definitions of the two tables are identical. What I was finally able to isolate was a table name that starts with a numeric value is not being recognized.
When I run this on ServerA:
Select *
from ServerB.Database1.dbo.Table1
The field with the numeric value is not shown in the results set of they query. The short term fix was to rename the field in the database, but why is this happening?
I am curious about the collation too, but really the answer is to wrap the object names in square brackets. i.e. SELECT [1col], [2col], [etc] FROM [1database].[2owner].[3table]. This way SQL with recognize each as an object name and not a function.
One other thing to keep in mind is to not use splat (*) in your select statement, this has potential problem of it's own. For example, you could run into an error in your Insert if the ServerA's table1 structure was change and ServerB's table one stayed the same.
I want to insert some data on the local server into a remote server, and used the following sql:
select * into linkservername.mydbname.dbo.test from localdbname.dbo.test
But it throws the following error
The object name 'linkservername.mydbname.dbo.test' contains more than the maximum number of prefixes. The maximum is 2.
How can I do that?
I don't think the new table created with the INTO clause supports 4 part names.
You would need to create the table first, then use INSERT..SELECT to populate it.
(See note in Arguments section on MSDN: reference)
The SELECT...INTO [new_table_name] statement supports a maximum of 2 prefixes: [database].[schema].[table]
NOTE: it is more performant to pull the data across the link using SELECT INTO vs. pushing it across using INSERT INTO:
SELECT INTO is minimally logged.
SELECT INTO does not implicitly start a distributed transaction, typically.
I say typically, in point #2, because in most scenarios a distributed transaction is not created implicitly when using SELECT INTO. If a profiler trace tells you SQL Server is still implicitly creating a distributed transaction, you can SELECT INTO a temp table first, to prevent the implicit distributed transaction, then move the data into your target table from the temp table.
Push vs. Pull Example
In this example we are copying data from [server_a] to [server_b] across a link. This example assumes query execution is possible from both servers:
Push
Instead of connecting to [server_a] and pushing the data to [server_b]:
INSERT INTO [server_b].[database].[schema].[table]
SELECT * FROM [database].[schema].[table]
Pull
Connect to [server_b] and pull the data from [server_a]:
SELECT * INTO [database].[schema].[table]
FROM [server_a].[database].[schema].[table]
I've been struggling with this for the last hour.
I now realise that using the syntax
SELECT orderid, orderdate, empid, custid
INTO [linkedserver].[database].[dbo].[table]
FROM Sales.Orders;
does not work with linked servers. You have to go onto your linked server and manually create the table first, then use the following syntax:
INSERT INTO [linkedserver].[database].[dbo].[table]
SELECT orderid, orderdate, empid, custid
FROM Sales.Orders
WHERE shipcountry = 'UK';
I've experienced the same issue and I've performed the following workaround:
If you are able to log on to remote server where you want to insert data with MSSQL or sqlcmd and rebuild your query vice-versa:
so from:
SELECT * INTO linkservername.mydbname.dbo.test
FROM localdbname.dbo.test
to the following:
SELECT * INTO localdbname.dbo.test
FROM linkservername.mydbname.dbo.test
In my situation it works well.
#2Toad: For sure INSERT INTO is better / more efficient. However for small queries and quick operation SELECT * INTO is more flexible because it creates the table on-the-fly and insert your data immediately, whereas INSERT INTO requires creating a table (auto-ident options and so on) before you carry out your insert operation.
I may be late to the party, but this was the first post I saw when I searched for the 4 part table name insert issue to a linked server. After reading this and a few more posts, I was able to accomplish this by using EXEC with the "AT" argument (for SQL2008+) so that the query is run from the linked server. For example, I had to insert 4M records to a pseudo-temp table on another server, and doing an INSERT-SELECT FROM statement took 10+ minutes. But changing it to the following SELECT-INTO statement, which allows the 4 part table name in the FROM clause, does it in mere seconds (less than 10 seconds in my case).
EXEC ('USE MyDatabase;
BEGIN TRY DROP TABLE TempID3 END TRY BEGIN CATCH END CATCH;
SELECT Field1, Field2, Field3
INTO TempID3
FROM SourceServer.SourceDatabase.dbo.SourceTable;') AT [DestinationServer]
GO
The query is run on DestinationServer, changes to right database, ensures the table does not already exist, and selects from the SourceServer. Minimally logged, and no fuss. This information may already out there somewhere, but I hope it helps anyone searching for similar issues.
I have 2 databases in SQL Server 2005.
I want a functionality that i have same table structure in 2 database for example i have a same table named as testData in 2 database named as dbTest1 and dbTest2.
Now i want a single query through which i can add all the records from table testData of database dbTest2 into table testData of database dbTest1.
I tried to use following query
insert into dbTest1.testData values select * from dbTest2.testData
but this query is not running and giving error.
I also tried
insert into dbTest1.testData(col1,col2,col3) values select * from dbTest2.testData
but this also gives error that "Invalid object name dbTest2.testData"
Could any one help in this
Thanks
Replace dbTest2.testData with dbTest2..testData - you have to specify 3 things (or optionally leave the middle blank for dbo).
i.e.
insert into dbTest1..testData
select * from dbTest2..testData
If the table doesn't already exist in dbTest1, you can do this:
select *
into dbTest1..testData
from dbTest2..testData
You need to specify all column names in query.
insert into dbTest1.dbo.testData(col1,col2,col3) select * from dbTest2.dbo.testData