Export/View data from a SQL Server temporary table - sql

I have a temporary table, that isn't going away. I want to see what is in the table to determine what bad data might be in there. How can I view the data in the temporary table?
I can see it in tempdb. I ran
SELECT * FROM tempdb.dbo.sysobjects WHERE Name LIKE '#Return_Records%'
to get the name of the table.
I can see it's columns and its object id in
select c.*
from tempdb.sys.columns c
inner join tempdb.sys.tables t ON c.object_id = t.object_id
where t.name like '#Return_Records%'
How can I get at the data?
By the way, this doesn't work
SELECT * FROM #Return_Records

One way of getting at the data in a low-level and not particularly easy to manipulate manner is to use the DBCC PAGE command as described in a blog post by Paul Randal:
http://blogs.msdn.com/sqlserverstorageengine/archive/2006/06/10/625659.aspx
You should be able to find the fileid and page number of the first page in the object by querying on sysindexes .. the last time I did this was on SQL Server 7.
If the data is in the database, then DBCC page will be able to dump it.
pjjH

SQL Server limits access to Local Temp Tables (#TableName) to the connection that created the table. Global temp tables (##TableName) can be accessible by other connections as long as the connection that created it is still connected.
Even though you can see the table in the table catalog, it is not accessible when trying to do a SELECT. It gives you an "Invalid Object Name" error.
There's no documented way of accessing the data in Local Temp Tables created by other connections. I think you may be out of luck in this case.

This is something that seems like you obviously tried, but since you didn't mention it I though I would mention just in case:
Did you try "SELECT * FROM #Return_Records"?

Like José Basilio says, that's a temporary table belonging to another connection. If it's there for a long time, it must belong to a connection that has been open for a long time. Check Maintenance -> Acitivity Monitor; you can sort by Login Time.
Check if the Login Time, or Last Batch Time, matches with the create date of the temporary table. That can be retrieved with:
select crdate from tempdb.dbo.sysobjects WHERE Name LIKE '#Return_Records%'
You can shoot down suspect connections (right click and Kill Process.) If the table is gone after killing a process, you've found the culprit.
To just remove the table, restart the SQL Server service. You can attach SQL Profiler right after with a filter to start looking for the connection that creates the temporary table.

Related

Object Variable in a query

I am using SSDT 2017 and I am working on a solution that basically gets a full result set from a query into a variable (1 column only: AccountID), and I need to include the values in that object variable in a query, something like this:
"SELECT * FROM dbo.account WHERE AccountID IN (" + #AccountIDObjectVariable + ")"
I tried with an expression but I get an error, so I am not sure if there's a better way, also I tried a for each loop container logic but since I have millions of record in the object variable I think that's not the best way.
Any idea?
It doesn't work that way. Where "it" is going to be a host of things.
The SSIS data types are primitive types (boolean, date, numbers) or Object. The only supported operations for Object is a null check and enumeration.
SSIS parameterization is only for equality based substitutions. There is no concept of a list data type in SQL so there's no analog in SSIS.
I have millions of record in the object variable
Even if you converted your list to a string and used string concatenation, the next problem you're going to run into is the string length limit of 4000 characters.
What is the way?
Let's reset the problem: You have a non-trivial set of identities from a source system. That set of ids needs to be used as the basis for a subsequent extract.
Is the source of identities and the actual data on the same server
While you can empty the ocean with a teaspoon, it's not the correct tool. Same holds true here. Move the query that identifies the recordset to be extracted into a filter condition for your source.
i.e.
Load dataset into #AccountIDObjectVariable
SELECT
OA.AccountId
FROM
dbo.OutstandingAccount AS OA;
Extract that isn't working
"SELECT * FROM dbo.account WHERE AccountID IN (" + #AccountIDObjectVariable + ")"
is rewritten as
SELECT * FROM dbo.account AS A WHERE EXISTS (SELECT * FROM dbo.OutstandingAccount AS OA WHERE OA.AccountID = A.AccountID);
There are two reasonable approaches for solving this
Pull it all
If the source ids list and the source table are of similar orders of magnitude, it might be easier to just bring it all down and use the account id generating query in a Lookup Task. If AccountID exists, then it's the data you want. Yes you pulled more than you wanted but you likely would have burned more cycles and complexity trying to selectively pull what you wanted.
Push and pull
This approach is going to work for SQL Server and I have no idea about any other database. Well, I suppose Sybase would be the same given database paternity.
Open SSMS and create a global temporary table on the database where dbo.account lives. Do not disconnect from SSMS.
IF OBJECT_ID('tempdb..##SO_66961235') IS NOT NULL
BEGIN
DROP TABLE ##SO_66961235;
END
GO
CREATE TABLE ##SO_66961235
(
AccountID int NOT NULL
);
Modify the Connection manager to set the RetainSameConnection Property to true for the database connection to dbo.account
Execute SQL Task - Make Temp Table
Use the connection to the account database and the above query. This will ensure the table exists for future sessions of SSIS to work.
DataFlow Load IDs
In the dataflow properties, set DelayValidation to True
Use your source query to generate the list of IDs and select the temporary table as the destination. You might need to have a second connection manager to this system running and pointed at tempdb, it's been a long time since I've done this. Same rule about RetainSameConnection will hold true though.
When this data flow completes, then we will have a temporary table on the data source server that we can reference.
Dataflow 2 Get Data
Again, DelayValidation to true.
Source will be a query
SELECT * FROM dbo.account AS A WHERE EXISTS (SELECT * FROM ##SO_66961235 AS OA WHERE OA.AccountID = A.AccountID);
What's with all the delay validation?
When the SSIS package starts, the first thing it does is ensure all the pieces are in place for it to run successfully and not only are the pieces in place, is the shape of the data still the same? A temporary table won't exist when the package starts and the package will fail with VS_NEEDSNEWMETADATA error. Setting DelayValidation tells SSIS that it should not worry about checking until the component actually gets the signal to start before it checks metadata. Since we defined the precursor Execute SQL Task to create the table, the validation should succeed.
I used global temporary tables here. You can use local scoped temporary tables but it makes the already fiddly design process much more so. Were it me, I'd have a package parameter controlling a boolean that uses a global temp table for development sessions and local temp table for actual run-time operations but that's beyond the scope of this question.

Trying to figure out how a table in SQL Server is getting populated

There is no documentation and no way to get in touch with the architects of the table. Are there any queries or options in SSMS that allows me to know what the table is connected to ?
A brief explanation of my issue is that there are two tables that seem to be connected.
Table A which contain 10M distinct users and Table B 5M users. All users in Table B are in Table A but obviously Table A's users aren't in Table B. After running multiple tests on the website, I cant find the trigger that copies the user information from Table A to Table B. And that's why I would like to know how Table B gets populated.
Like Diado already said, try running a profiler for a while. It will log queries against the database (e.g. INSERT ... and UPDATE ...), the source of the connection (e.g. IP address), and sometimes the process name. That could provide clues into what's interacting with your table in question.
https://learn.microsoft.com/en-us/sql/tools/sql-server-profiler/sql-server-profiler?view=sql-server-2017

Query that falls back to different table if linked server query fails

Our test database is linked to a database owned by another department within our company. Whenever they bring their database down (like when refreshing with production data) our application goes down as well. The only thing we are doing with their database is we have a view that selects from one of their tables and we join to this view in a number of queries.
Ideally, whenever their system goes down, I'd like our view to pull from a backup of their table that exists in our database. It has slightly stale data, but at least we would be able to continue working. I thought of using a TRY...CATCH in the view or in a sql function, but they are not supported in those. A stored procedure might work, except that you can't join to the results of a stored procedure in queries, can you?
How can I make my SELECT statements fall back to a backup table when the linked server's table is unavailable?
So what I ended up doing was to create a SQL Server Agent job that calls sp_testlinkedserver in a TRY...CATCH every few minutes and if it's down we alter the view to point to our backup table and if it's up, we alter it to point to the "live" data again. We also track the previous state so we only alter the view if the state has changed. It works pretty slick.

How to delete a large record from SQL Server?

In a database for a forum I mistakenly set the body to nvarchar(MAX). Well, someone posted the Encyclopedia Britanica, of course. So now there is a forum topic that won't load because of this one post. I have identified the post and ran a delete query on it but for some reason the query just sits and spins. I have let it go for a couple hours and it just sits there. Eventually it will time out.
I have tried editing the body of the post as well but that also sits and hangs. When I sit and let my query run the entire database hangs so I shut down the site in the mean time to prevent further requests while it does it's thinking. If I cancel my query then the site resumes as normal and all queries for records that don't involve the one in question work fantastically.
Has anyone else had this issue? Is there an easy way to smash this evil record to bits?
Update: Sorry, the version of SQL Server is 2008.
Here is the query I am running to delete the record:
DELETE FROM [u413].[replies] WHERE replyID=13461
I have also tried deleting the topic itself which has a relationship to replies and deletes on topics cascade to the related replies. This hangs as well.
Option 1. Depends on how big the table itself and how big are the rows.
Copy data to a new table:
SELECT *
INTO tempTable
FROM replies WITH (NOLOCK)
WHERE replyID != 13461
Although it will take time, table should not be locked during the copy process
Drop old table
DROP TABLE replies
Before you drop:
- script current indexes and triggers so you are able to recreate them later
- script and drop all the foreign keys to the table
Rename the new table
sp_rename 'tempTable', 'replies'
Recreate all the foreign keys, indexes and triggers.
Option 2. Partitioning.
Add a new bit column, called let's say 'Partition', set to 0 for all rows except the bad one. Set it to 1 for bad one.
Create partitioning function so there would be two partitions 0 and 1.
Create a temp table with the same structure as the original table.
Switch partition 1 from original table to the new temp table.
Drop temp table.
Remove partitioning from the source table and remove new column.
Partitioning topic is not simple. There are some examples in the internet, e.g. Partition switching in SQL Server 2005
Start by checking if your transaction is being blocked by another process. To do this, you can run this command..
SELECT * FROM sys.dm_os_waiting_tasks WHERE session_id = {spid}
Replace {spid} with the correct spid number of the connection running your DELETE command. To get that value, run SELECT ##spid before the DELETE command.
If the column sys.dm_os_waiting_tasks.blocking_session_id has a value, you can use activity monitor to see what that process is doing.
To open activity monitor, right-click on the server name in SSMS' Object Explorer and choose Activity Monitor. The Processes and Resource Waits sections are the ones you want.
Since you're having issues deleting the record and recreating the table, have you tried updating the record?
Something like (changing "body" field name to whatever it is in the table):
update [u413].[replies] set body='' WHERE replyID=13461
Once you clear out the text from that single reply record you should be able to alter the data type of the column to set an upper bound. Something like:
alter table [u413].[replies] alter column body nvarchar(100)

View Temporary Table Created from Stored Procedure

I have a stored procedure in SQL 2005. The Stored Procedure is actually creating temporary tables in the beginning of SP and deleting it in the end. I am now debugging the SP in VS 2005. In between the SP i would want to know the contents into the temporary table. Can anybody help in in viewing the contents of the temporary table at run time.
Thanks
Vinod T
There are several kinds of temporary tables, I think you could use the table which is not dropped after SP used it. Just make sure you don't call the same SP twice or you'll get an error trying to create an existing table. Or just drop the temp table after you see it's content. So instead of using a table variable (#table) just use #table or ##table
From http://arplis.com/temporary-tables-in-microsoft-sql-server/:
Local Temporary Tables
Local temporary tables prefix with single number sign (#) as the first character of their names, like (#table_name).
Local temporary tables are visible only in the current session OR you can say that they are visible only to the current connection for the user.
They are deleted when the user disconnects from instances of Microsoft SQL Server.
Global temporary tables
Global temporary tables prefix with double number sign (##) as the first character of their names, like (##table_name).
Global temporary tables are visible to all sessions OR you can say that they are visible to any user after they are created.
They are deleted when all users referencing the table disconnect from Microsoft SQL Server.
Edit the stored procedure to temporarily select * from the temp tables (possibly into another table or file, or just to the output pane) as it runs..?
You can then change it back afterwards. If you can't mess with the original procedure, copy it and edit the copy.
I built a few stored procedures which allow you to query the content of a temp table created in another session.
See sp_select project on github.
The content of the table can be displayed by running exec sp_select 'tempdb..#temp' from no matter which session.
Bottom line: the default Visual Studio Microsoft debugger is not in the same session as the SQL code being executed and debugged.
So you can ONLY look at #temp tables by switching them to global ##temp tables or permanent tables or whatever technique you like best that works across sessions.
note: this is VERY different from normal language debuggers... and I suspect kept
that way by Microsoft on purpose... I've seen third party SQL debugger tools decades ago
that didn't have this problem.
There is no good technical reason why the debugger cannot be in the same session as your SQL code, thus allowing you to examine all produced contructs including #temp tables.
To expand on previous suggestions that you drop the data into a permanent table, you could try the following:
-- Get rid of the table if it already exists
if object_id('TempData') is not null
drop table TempData
select * into TempData from #TempTable
This helped me.
SELECT * FROM #Name
USE [TEMPDB]
GO
SELECT * FROM syscolumns
WHERE id = ( SELECT id FROM sysobjects WHERE [Name] LIKE '#Name%')
this gives the details of all the temp table