Removing allocated space for Table - SQL Server - sql-server

I got a table where in got allocated space of 3gig but have no rows.
How to remove this allocated space ?

There are some restriction with TRUNCATE TABLE, and if can't do a truncate then you can rebuild your clustered index to free up the allocated space.
You cannot use TRUNCATE TABLE on tables that:
Are referenced by a FOREIGN KEY
constraint. (You can truncate a table
that has a foreign key that
references itself.)
Participate in an indexed view.
Are published by using transactional
replication or merge replication.
If the table contains an identity column, the counter for that column is reset to the seed value defined for the column. If no seed was defined, the default value 1 is used. To retain the identity counter, use DELETE instead. If this is the case then you need to reseed the table to continue the identity increment from where it was.
If the table does not have a clustered index you can use TABLOCK hint in your DELETE statement to free up the allocated space.
DELETE FROM table WITH (TABLOCK)
If table is using a clustered index you can rebuild the index to free the space.

You can do:
truncate table [table_name]
Then in Sql Server Express Manager, right click on the database and go to tasks->shrink->database/files (do both). Should clear you up.

These should do it, they will shrink your database files. If the table is empty the reserved space for the table will be released with the following commands
DBCC SHRINKDATABASE ('DBName')
DBCC SHRINKFILE ('LogicalFileName')

Related

SQL Server TRUNCATE

I have a question to the TRUNCATE command.
How does TRUNCATE work in background ?
I read a text that says TRUNCATE creates a copy from the table and then start to delete all rows of the table. Is it correct?
with the information from here
TRUNCATE logs the deallocation of the data pages in which the data
exists which means that your data rows still actually exist in the data pages, but the extents have been marked as empty for reuse. This is what
makes TRUNCATE a faster operation to perform over DELETE.
You cannot TRUNCATE a table that has any foreign key
constraints. You will have to remove the contraints, TRUNCATE the
table, and reapply the contraints.
TRUNCATE will reset any identity columns to the default seed
value. This means if you have a table with an identity column and
you have 264 rows with a seed value of 1, your last record will have
the value 264 (assuming you started with value 1) in its identity
columns. After TRUNCATEing your table, when you insert a new
record into the empty table, the identity column will have a value of
1

Primary Key Resetting Issue with foreign keys and delete

I have a set of tables which I am going to clear out and upload new data into. One of these, Person has foreign keys pointing to it which prevent me from using TRUNCATE Table even though the other tables are empty.
I have used DELETE FROM after turning off the foreign key checks to get around this. This works except when I insert new values they start at the old value going up and I need them to reset to start at 1 again (or at least some consistent predictable value)
DBCC CHECKIDENT ([Person], RESEED, -1); or DBCC CHECKIDENT ([Person], RESEED, 0); I have seen suggested on other places for resetting the identity but give no useful results for me instead yielding:
Checking identity information: current identity value 'NULL'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
How can I either get truncate to work with the foreign keys pointing to my table OR using delete to clear the table get the primary key's auto increment to reset and start at 1?
You cannot truncate a table, if there are foreign keys pointing to it.
One way would be, to temporarily drop the foreign keys and after truncating recreate them.
Disabling foreign key constraint, still can't truncate table? (SQL Server 2005)
The DBCC command should work. I have removed the square brackets and added single quotes:
DBCC CHECKIDENT ('dbo.Person', RESEED, 0);

Converting int primary key to bigint in Sql Server

We have a production table with 770 million rows and change. We want(/need?) to change the Primary ID column from int to bigint to allow for future growth (and to avoid the sudden stop when the 32bit integer space is exhausted)
Experiments in DEV have shown that this is not as simple as altering the column as we would need to drop the index and then re-create it. So far in DEV (which is a bit humbler than PROD) the dropping of the index has not finished after 1 and a half hours. This table is hit 24/7 and having it offline for such a long time is not an option.
Has anyone else had to deal with a similar situation? How did you get it done?
Are there alternatives?
Edit: Additional Info:
The Primary key is clustered.
You could attempt a staged approach.
Create a new bigint column
Create an insert trigger to keep new entries in sync with the 2 columns
Execute an update to populate all the empty values in the bigint column with the converted value
Change the primary index on the table from your old id column to the new one
Point any FK's and queries to use the new column
Change the new column to become your identity column and remove the insert trigger from #2
Delete the old ID column
You should end up spreading the pain out over these 7 steps instead of hitting it all at once.
Create a parallel table with the longer data type for new rows and UNION the results?
What I had to do was copy the data into a new table with the desired structure (primary/clustered key only, non-clustered/FK once complete). If you don't have the room, you could bcp out the data and back in. You may need an application outage to make this happen.
What doesn't work: alter table Orderhistory alter column ID bigint because of the primary key. Don't drop the key and alter column as you will just fill your log file and take much longer than copy/bcp.
Never use the SSMS tools designer to change a column property, it copies table into temp table then does a rename once done. Lookup the alter table alter column syntax and use it and possibly defrag once complete if you modified a column wider that sits in middle of table.

Undo Table Partitioning

I have a table 'X' and did the following
CREATE PARTITION FUNCTION PF1(INT) AS RANGE LEFT FOR VALUES (1, 2, 3, 4)
CREATE PARTITION SCHEME PS1 AS PARTITION PF1 ALL TO ([PRIMARY])
CREATE CLUSTERED INDEX CIDX_X ON X(col1) ON PS1(col1)
this 3 steps created 4 logical partitions of the data I had.
My question is, how do I revert this partitioning to its original state ?
After 2 days of continuous searching
The Steps:
DROP INDEX CIDX_X on X /* drop the clustered */
CREATE CLUSTERED INDEX CIDX_X1 ON X(col1) ON [PRIMARY] /* Create another clustered index on the table to free it from the partitioning scheme; Here, the "ON [primary]" part is key to removing the partition scheme from the table ! */
DROP PARTITION SCHEME PS1
DROP PARTITION FUNCTION PF1
DROP INDEX CIDX_X1 ON X /* drop the dummy clustered index you created, as it was only created to free the table from the partitioning scheme */
I found that some additional steps should be added to the answer given by Storm, since, there are some points like ... before deleting the clustered index, the publication needs to be dropped because it wont allow the clustered index to get dropped before that and after dropping those partition-scheme and partition function needs to be recreated, and publication also again needs to be started.
Note: I am using SQL 2012
Primary key is normally the most commonly used clustered constraint, so wherever i used primary key, consider that those steps also apply to Clustered constraints too. Also, PS= Partition Scheme, PF = Partition Function.
Some preparatory steps:
Make a drop publication script
Make a create publication script
Identify all tables who have dependencies with the Partition Scheme,and also note down their primary key/clustered index.Also, note down all the fields which the primary key column uses (better to generate the script for primary key or clustered index)
Make a script for tables getting affected.
Make a script for PF and PS that are in question.
All the above, using SQL Management Studio "generate scripts" upon right click. And choose drop and create.
Now, when everything is ready.
1. Drop the publication (use the script that you generated)
2. Drop the Primary key constraint of those tables which are linked with the PS.
alter table [tablename] drop constraint [pk_name]
3. Make a dummy constraint but use the same fields that you used in that deleted primary key. CREATE CLUSTERED INDEX CIDX_X1 ON tablename(field1,field2,field3,field4) ON [PRIMARY]
4. drop the partition scheme and function.
DROP PARTITION SCHEME [PartitionSchemeName_PS]
GO
DROP PARTITION FUNCTION [PartitionfunctionName_PF]
GO
Drop the Dummy Index
DROP INDEX CIDX_X1 ON tablename
Add back the Clustered index/primary key constraint(using the generated scripts as mentioned earlier.
Create the Partition function and Partition schema (ensure that the number of elements of PS > PF. where PS = PF+2 elements)
Add back the publisher (use the generated scripts)

Changing Identity Seed in SQL Server (Permanently!)

Is there any way of changing the identity seed for an identity column permanently? Using DBCC CHECKIDENT just seems to set the last_value. If the table is truncated all values are reset.
dbcc checkident ('__Test_SeedIdent', reseed, 1000)
select name, seed_value, increment_value, last_value
from sys.identity_columns
where [object_id] = OBJECT_ID('__Test_SeedIdent');
returns
name seed_value increment_value last_value
-------------------------------------------------
idIdent 1 1 1000
I was hoping that some syntax like
alter table dbo.__Test_SeedIdent alter column idIdent [int] identity(1000,1) NOT NULL
would exist.
Is it necessary to create a new column, move the values across, drop the original column and rename the new?
From Books Online:
"To change the original seed value and reseed any existing rows, you must drop the identity column and recreate it specifying the new seed value. When the table contains data, the identity numbers are added to the existing rows with the specified seed and increment values. The order in which the rows are updated is not guaranteed."
MSSQL does not allow you to add or alter an Identity on an existing column via TSQL very easily. You would have to drop the column and re-add it. Needless to say this can play hell with FK relations. You can do it directly in the enterprise manager. However that won't be fun if you have to do this to a LOT of columns.
Is it necessary to create a new
column, move the values across, drop
the original column and rename the
new?
Yup, and don't forget to fix/update all indexes, foreign key relationships, etc. that are tied to that column
You can use DBCC CHECKIDENT('tablename', RESEED, seedvalue)
example: DBCC CHECKIDENT('Customers',RESEED, 1350)
run DBCC CHECKIDENT('Customers') again to check if current seed value was set.
However as mentioned in previous answers this will not change existing values stored in the identity column. It will only change seed value so the next row that is inserted will start with that value. Identity increment remains same (not changed) and can not be changed with DBCC.
"Is it necessary to create a new column, move the values across, drop the original column and rename the new?"
Actually in Enterprise Manager, when you add an ID column to an existing table (or change an INT PK field to an INT PK ID), it does this behind the scene.

Resources