The object name 'FacetsXrefStaging.Facets.Facets.FacetsXrefImport' contains more than the maximum number of prefixes. The maximum is 2 - sql

Hi i have created a proc which truncates and reseeds the no of records from the tables. but i am getting the error : The object name 'FacetsXrefStaging.Facets.Facets.FacetsXrefImport' contains more than the maximum number of prefixes. The maximum is 2.
Create proc TruncateAndReseedFacetsXrefStagingTables
'
'
Declare variables
'
'
SET #iSeed = ( SELECT CASE WHEN MAX(FacetsXrefId) IS NULL
THEN -2147483648
ELSE MAX(FacetsXrefId) + 1
END
FROM FacetsXref.Facets.Facets.FacetsXrefCertified
)
TRUNCATE TABLE FacetsXrefStaging.Facets.Facets.FacetsXrefImport
DBCC CHECKIDENT ('FacetsXrefStaging.Facets.FacetsXrefImport', RESEED,#iSeed )
TRUNCATE TABLE FacetsXrefStaging.Facets.FacetsXrefImport
Can anybody help me with that.
I AM USING SQL SERVER 2005.

I am actually having this problem that the OP had - and there's no typo involved in my situation. :-)
This is a table that exists on a different server from the server I'm on. The servers are linked.
The queries above and below the TRUNCATE statement work just fine.
The TRUNCATE does not work.
...Anonymized to protect the innocent...
select count(*) as mc from servername.databasename.dbo.tablename -- works
truncate TABLE [servername].[databasename].[dbo].[tablename] -- error
select count(*) as mc from servername.databasename.dbo.tablename -- works
Error message:
The object name 'servername.databasename.dbo.'
contains more than the maximum number of prefixes. The maximum is 2.
Yes - the TRUNCATE is commented but I noticed that after I did all the blur effects and wasn't going to go back and re-make the image - sorry :-( - ignore the begin/end tran and the comment markers - the TRUNCATE does not work - see error above.

Related

Same query, different result after removing USE DatabaseName GO

My function GetProductDesc (when called) returns a different result after commenting out USE DatabaseName GO. I don't even know where to start debugging this. The pictures tell the story. I had to blur out a lot but you can see that the results are clearly different. Keep in mind that the pictures are not the function code, they are calling the function GetProductDesc
So strange. Any suggestions? I have an expert helping me later today but I had to share.
EDIT:
The function uses another lookup table in the same database. There is no Top or Order By clause. It calculates the product description based on the input components (numbers). It will return a different result if the input numbers are different, but here the input numbers are the same!
The function has been in place and working for over 5 years. I believe the problem started at about the time the version of SQL Server was updated recently.
EDIT 2 with partial answer:
The problem is caused by ##RowCount. It appears to be a breaking change caused by our recent migration to SQL Server 2019 although I haven't found the problem documented. The function returns a different product description based on ##RowCount following a Select statement. Internally the function does something like this:
SELECT Fields FROM Table WHERE Field = #Variable
IF ##Rowcount = 1
Return ProdDesc1
ELSE
Return ProdDesc2
After the SQL Server migration ##RowCount here was different depending on whether
USE DatabaseName
GO
was present.
The solution was to replace ##Rowcount with a variable #RowCount. This new code works:
DECLARE #RowCount INT = 0
SELECT Fields, #RowCount = #RowCount + 1
FROM Table WHERE Field = #Variable
IF #RowCount = 1
Return ProdDesc1
ELSE
Return ProdDesc2
If you have SQL Server 2019 installed try this to recreate the problem:
USE Master
GO
Select ##ROWCOUNT
The result here is ##ROWCOUNT = 0
Now comment out the two top lines:
--USE Master
--GO
Select ##ROWCOUNT
The result is now ##ROWCOUNT = 1
Anybody know why?
There is a SQL Server 2019 cumulative update from Microsoft that fixes this problem.

Updating first 7 characters of string with another 3 characters using SQL, throws "Error 19 - UNIQUE constraint failed: MGOFile.File."

I have a rather simple DB with a column called File, and I need to remove the first 7 characters of each row, and replace with a new string. I thought I had the code sorted, but I am getting error "SQLite3 Error 19 - UNIQUE constraint failed: MGOFile.File."
My table name is MGOFile, and the column is File. This is a simple select statement on the first few rows, the left column is the raw data, the right is what I need the resultant rows to look like...
I query my table using this:
'''sql
SELECT
File,
'T:\'|| substr(File, 8,2000) as File
FROM
MGOFile
WHERE
file like 'M:\_TV%';
'''
I then tried updating using this:
UPDATE MGOFile
SET File = 'T:\' || substr(File, 8, 2000)
WHERE File like 'M:\_TV%';
But here is where my error comes in, this fails with an error:
I am sure I am doing something simple wrong, but I have done plenty of Googling but all responses are over my head, this is the most advanced SQL I have tried to do!
Any ideas on how to can update these strings with some simple SQLite?
As checking for duplicates doesn't appear to detect the issues. Perhaps getting values at the time of the issue may assist. Do you have Triggers by any-chance? These will sometimes propagate an error which will be reported as being with the table that triggered the trigger.
As such perhaps consider adding a table to log such data along with a BEFORE UPDATE TRIGGER to actually log the information at run time. To stop the data being rolled back and thus undoing the logged information OR FAIL needs to be used.
Important as the updates will not be rolled back updates will have been applied. It is suggested that the above is used on a test database.
-- The code
DROP TABLE IF EXISTS lastupdated;
-- Create the logging table
CREATE TABLE IF NOT EXISTS lastupdated (counter, lastfile_before, lastfile_after, id_of_the_row);
-- Initialise it so it's plain to see if nothing has been done
INSERT INTO lastupdated VALUES(0,'nothing','nothing',0);
-- Add the Trigger to record the debugging information BEFORE the update
CREATE TRIGGER IF NOT EXISTS monitorupdateprogress
BEFORE UPDATE ON MGOFile
BEGIN
UPDATE lastupdated SET counter = counter +1, lastfile_before = old.File, lastfile_after = new.File, id_of_the_row = old.rowid;
END
;
UPDATE OR FAIL MGOFile -- OR FAIL will halt but NOT ROLLBACK
SET File = 'T:\' || substr(File, 8, 2000)
WHERE File like 'M:\_TV%';
SELECT * FROM lastupdated; -- will not run if there is a fail but should be run after the fail
This would, assuming the fail, record
the nth update in the counter column
the value in the File column before the change in the lastfile_before column.
the value that the File column would be updated to in the **lastfile_after* columns.
the last rowid (failing) of the row in the MGOFile table (this does assume that the MGOFile table is not a table defined using WITHOUT ROWID).
If the table was defined with the WITHOUT ROWID then you could change , id_of_the_row = 0;. The value will then be meaningless.
Testing/Results the version of the above that was used to test the above is :-
-- Solely for testing the code below
DROP TABLE IF EXISTS MGOFile;
CREATE TABLE IF NOT EXISTS MGOFile (File TEXT PRIMARY KEY);
-- Some testing data
INSERT INTO MGOFile VALUES
('M:\_TV/9-1-1.so2e09.web.x264-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x265-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x277-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x278-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x279-tbs[eztv].mkv'),
('M:\_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x280-tbs[eztv].mkv')
;
SELECT substr(File,170,8) FROM MGOFile GROUP BY Substr(File,8,170) HAVING count() > 1;
-- The code
DROP TABLE IF EXISTS lastupdated;
-- Create the logging table
CREATE TABLE IF NOT EXISTS lastupdated (counter, lastfile_before, lastfile_after, id_of_the_row);
-- Initialise it so it's plain to see if nothing has been done
INSERT INTO lastupdated VALUES(0,'nothing','nothing',0);
-- Add the Trigger to record the debugging information BEFORE the update
CREATE TRIGGER IF NOT EXISTS monitorupdateprogress
BEFORE UPDATE ON MGOFile
BEGIN
UPDATE lastupdated SET counter = counter +1, lastfile_before = old.File, lastfile_after = new.File, id_of_the_row = old.rowid;
END
;
SELECT * FROM MGOFile;
UPDATE OR FAIL MGOFile -- OR FAIL will halt but NOT ROLLBACK
SET File = 'T:\' || substr(File, 8, 170) -- <<<<<<<<<<<<<<<<<<<< truncate reduced to force UNIQUE constraint
WHERE File like 'M:\_TV%';
SELECT * FROM lastupdated; -- will not run if there is a fail
When the above is run then the message is :-
UPDATE OR FAIL MGOFile -- OR FAIL will halt but NOT ROLLBACK
SET File = 'T:\' || substr(File, 8, 170) -- <<<<<<<<<<<<<<<<<<<< truncate reduced to force UNIQUE constraint
WHERE File like 'M:\_TV%'
> UNIQUE constraint failed: MGOFile.File
> Time: 0.094s
Running SELECT * FROM lastupdated; returns :-
counter
6
lastfile_before =
M:_TV/9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x278-tbs[eztv].mkv
lastfile_after
T:\9-1-1.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x266-tbs[eztv].mkv.so2e09.web.x27
id_of_the_row
6
In the above contrived example the issue can easily be determined (albeit that the duplicate search also found the same issue) as the error is on the 6th row and at the row that contains mkv.so2e09.web.x278-tbs[eztv] but was truncated by the update to .mkv.so2e09.web.x27 hence it is a duplicate of the 5th row which has .mkv.so2e09.web.x277-tbs[eztv] but was also truncated to .mkv.so2e09.web.x27.
P.S. Have you tried using just
UPDATE MGOFile
SET File = 'T:\' || substr(File, 8)
WHERE File like 'M:\_TV%';
i.e. removing the truncation.
The error seems quite clear to me. You are changing the file name to a name that is already in the table.
You can identify the duplicates by running:
SELECT f.*
FROM MGOFile f
WHERE EXISTS (SELECT 1
FROM MGOFile f2
WHERE f2.File = 'T:\'|| substr(File, 8,2000)
) AND
f.file LIKE 'M:\_TV%';
I don't know what you want to do about the duplicate.

SQL Maximum Recursion Causes Failure

I can't remember where I got this, but probably SO so sorry to original poster. I have been using it wonderfully for quiet some time with perfect results. Today however I ran into a problem. I am running it through SSRS with a list of around 1500 item. Naturally someone is going to click "ALL" even though they really never will want all, however, when they do, is errors out
An error occurred during local report processing. An error has
occurred during report processing. Cannot read the next data row for
the data set Accounts. The statement terminated. The maximum recursion
100 has been exhausted before statement completion.
here is the code: Is this a SQL thing or a code thing?
ALTER FUNCTION [dbo].[ParseCSV] (#CSV_STR VARCHAR(8000),#Delimiter varchar(20) )
RETURNS #splittable TABLE (ID int identity(1,1), CSVvalues VARCHAR(256) )
AS
BEGIN
-- Check for NULL string or empty sting
IF (LEN(#CSV_STR) < 1 OR #CSV_STR IS NULL)
BEGIN
RETURN
END
; WITH csvtbl(i,j)
AS
(
SELECT i=1, j= CHARINDEX(#Delimiter,#CSV_STR+#Delimiter)
UNION ALL
SELECT i=j+1, j=CHARINDEX(#Delimiter,#CSV_STR+#Delimiter,j+1)
FROM csvtbl
WHERE CHARINDEX(#Delimiter,#CSV_STR+#Delimiter,j+1) <> 0
)
INSERT INTO #splittable ( CSVvalues)
SELECT LTRIM(RTRIM(SUBSTRING(#CSV_STR,i,j-i)))
FROM csvtbl
RETURN
END
Save everyone some time. Its not exactly a duplicate but the same response would fix it. It is a SQL this :
The maximum recursion 100 has been exhausted before statement completion error showing in SQL Query
The default maximum number of recursions for a recursive CTE is 100. You need to set OPTION MAXRECURSION number on your SELECT statement where number is anything between 0 and 32767 and 0 is no limit. Obviously be careful setting the number to 0 as you could potentially get an infinite loop.

How to force a running t-sql query (half done) to commit?

I have database on Sql Server 2008 R2.
On that database a delete query on 400 Million records, has been running for 4 days , but I need to reboot the machine. How can I force it to commit whatever is deleted so far? I want to reject that data which is deleted by running query so far.
But problem is that query is still running and will not complete before the server reboot.
Note : I have not set any isolation / begin/end transaction for the query. The query is running in SSMS studio.
If machine reboot or I cancelled the query, then database will go in recovery mode and it will recovering for next 2 days, then I need to re-run the delete and it will cost me another 4 days.
I really appreciate any suggestion / help or guidance in this.
I am novice user of sql server.
Thanks in Advance
Regards
There is no way to stop SQL Server from trying to bring the database into a transactionally consistent state. Every single statement is implicitly a transaction itself (if not part of an outer transaction) and is executing either all or nothing. So if you either cancel the query or disconnect or reboot the server, SQL Server will from transaction log write the original values back to the updated data pages.
Next time when you delete so many rows at once, don't do it at once. Divide the job in smaller chunks (I always use 5.000 as a magic number, meaning I delete 5000 rows at the time in the loop) to minimize transaction log use and locking.
set rowcount 5000
delete table
while ##rowcount = 5000
delete table
set rowcount 0
If you are deleting that many rows you may have a better time with truncate. Truncate deletes all rows from the table very efficiently. However, I'm assuming that you would like to keep some of the records in the table. The stored procedure below backs up the data you would like to keep into a temp table then truncates then re-inserts the records that were saved. This can clean a huge table very quickly.
Note that truncate doesn't play well with Foreign Key constraints so you may need to drop those then recreate them after cleaned.
CREATE PROCEDURE [dbo].[deleteTableFast] (
#TableName VARCHAR(100),
#WhereClause varchar(1000))
AS
BEGIN
-- input:
-- table name: is the table to use
-- where clause: is the where clause of the records to KEEP
declare #tempTableName varchar(100);
set #tempTableName = #tableName+'_temp_to_truncate';
-- error checking
if exists (SELECT [Table_Name] FROM Information_Schema.COLUMNS WHERE [TABLE_NAME] =(#tempTableName)) begin
print 'ERROR: already temp table ... exiting'
return
end
if not exists (SELECT [Table_Name] FROM Information_Schema.COLUMNS WHERE [TABLE_NAME] =(#TableName)) begin
print 'ERROR: table does not exist ... exiting'
return
end
-- save wanted records via a temp table to be able to truncate
exec ('select * into '+#tempTableName+' from '+#TableName+' WHERE '+#WhereClause);
exec ('truncate table '+#TableName);
exec ('insert into '+#TableName+' select * from '+#tempTableName);
exec ('drop table '+#tempTableName);
end
GO
You must know D(Durability) in ACID first before you understand why database goes to Recovery mode.
Generally speaking, you should avoid long running SQL if possible. Long running SQL means more lock time on resource, larger transaction log and huge rollback time when it fails.
Consider divided your task some id or time. For example, you want to insert large volume data from TableSrc to TableTarget, you can write query like
DECLARE #BATCHCOUNT INT = 1000;
DECLARE #Id INT = 0;
DECLARE #Max = ...;
WHILE Id < #Max
BEGIN
INSERT INTO TableTarget
FROM TableSrc
WHERE PrimaryKey >= #Id AND #PrimaryKey < #Id + #BatchCount;
SET #Id = #Id + #BatchCount;
END
It's ugly more code and more error prone. But it's the only way I know to deal with huge data volume.

Is my stored procedure executing out of order?

Brief history:
I'm writing a stored procedure to support a legacy reporting system (using SQL Server Reporting Services 2000) on a legacy web application.
In keeping with the original implementation style, each report has a dedicated stored procedure in the database that performs all the querying necessary to return a "final" dataset that can be rendered simply by the report server.
Due to the business requirements of this report, the returned dataset has an unknown number of columns (it depends on the user who executes the report, but may have 4-30 columns).
Throughout the stored procedure, I keep a column UserID to track the user's ID to perform additional querying. At the end, however, I do something like this:
UPDATE #result
SET Name = ppl.LastName + ', ' + ppl.FirstName
FROM #result r
LEFT JOIN Users u ON u.id = r.userID
LEFT JOIN People ppl ON ppl.id = u.PersonID
ALTER TABLE #result
DROP COLUMN [UserID]
SELECT * FROM #result r ORDER BY Name
Effectively I set the Name varchar column (that was previously left NULL while I was performing some pivot logic) to the desired name format in plain text.
When finished, I want to drop the UserID column as the report user shouldn't see this.
Finally, the data set returned has one column for the username, and an arbitrary number of INT columns with performance totals. For this reason, I can't simply exclude the UserID column since SQL doesn't support "SELECT * EXCEPT [UserID]" or the like.
With this known (any style pointers are appreciated but not central to this problem), here's the problem:
When I execute this stored procedure, I get an execution error:
Invalid column name 'userID'.
However, if I comment out my DROP COLUMN statement and retain the UserID, the stored procedure performs correctly.
What's going on? It certainly looks like the statements are executing out of order and it's dropping the column before I can use it to set the name strings!
[Edit 1]
I defined UserID previously (the whole stored procedure is about 200 lies of mostly irrelevant logic, so I'll paste snippets:
CREATE TABLE #result ([Name] NVARCHAR(256), [UserID] INT);
Case sensitivity isn't the problem but did point me to the right line - there was one place in which I had userID instead of UserID. Now that I fixed the case, the error message complains about UserID.
My "broken" stored procedure also works properly in SQL Server 2008 - this is either a 2000 bug or I'm severely misunderstanding how SQL Server used to work.
Thanks everyone for chiming in!
For anyone searching this in the future, I've added an extremely crude workaround to be 2000-compatible until we update our production version:
DECLARE #workaroundTableName NVARCHAR(256), #workaroundQuery NVARCHAR(2000)
SET #workaroundQuery = 'SELECT [Name]';
DECLARE cur_workaround CURSOR FOR
SELECT COLUMN_NAME FROM [tempdb].INFORMATION_SCHEMA.Columns WHERE TABLE_NAME LIKE '#result%' AND COLUMN_NAME <> 'UserID'
OPEN cur_workaround;
FETCH NEXT FROM cur_workaround INTO #workaroundTableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #workaroundQuery = #workaroundQuery + ',[' + #workaroundTableName + ']'
FETCH NEXT FROM cur_workaround INTO #workaroundTableName
END
CLOSE cur_workaround;
DEALLOCATE cur_workaround;
SET #workaroundQuery = #workaroundQuery + ' FROM #result ORDER BY Name ASC'
EXEC(#workaroundQuery);
Thanks everyone!
A much easier solution would be to not drop the column, but don't return it in the final select.
There are all sorts of reasons why you shouldn't be returning select * from your procedure anyway.
EDIT: I see now that you have to do it this way because of an unknown number of columns.
Based on the error message, is the database case sensitive, and so there's a difference between userID and UserID?
This works for me:
CREATE TABLE #temp_t
(
myInt int,
myUser varchar(100)
)
INSERT INTO #temp_t(myInt, myUser) VALUES(1, 'Jon1')
INSERT INTO #temp_t(myInt, myUser) VALUES(2, 'Jon2')
INSERT INTO #temp_t(myInt, myUser) VALUES(3, 'Jon3')
INSERT INTO #temp_t(myInt, myUser) VALUES(4, 'Jon4')
ALTER TABLE #temp_t
DROP Column myUser
SELECT * FROM #temp_t
DROP TABLE #temp_t
It says invalid column for you. Did you check the spelling and ensure there even exists that column in your temp table.
You might try wrapping everything preceding the DROP COLUMN in a BEGIN...COMMIT transaction.
At compile time, SQL Server is probably expanding the * into the full list of columns. Thus, at run time, SQL Server executes "SELECT UserID, Name, LastName, FirstName, ..." instead of "SELECT *". Dynamically assembling the final SELECT into a string and then EXECing it at the end of the stored procedure may be the way to go.