I've been comparing databases using vs 2010 scheme comparing tool and it generated some stuff which is not clear. For example at the end of the script it has this statement:
ALTER TABLE [dbo].[My_table] WITH CHECK CHECK CONSTRAINT [FK_FOREIGN_ID];
Can anyone explain what this means?
It means that existing data should be checked against the constraint when it is added.
Failure to have the CHECK CHECK leaves your constraints untrusted and they cannot be used by the query optimiser.
That tells SQL Server to validate the constraint against new rows. The counter example would be to use WITH NOCHECK to temporarily disable validation checks for new rows.
ALTER TABLE (Transact-SQL) (WITH CHECK | WITH NOCHECK )
Related
I am working on SDL Server 2008 R2, where I generated a schema-only database script. The generated script is as follows:
ALTER TABLE [dbo].[ConsoleServer] WITH CHECK ADD CONSTRAINT [FK_ConsoleServer_RackUnits] FOREIGN KEY([RackUnitID])
REFERENCES [dbo].[RackUnits] ([UnitID])
GO
ALTER TABLE [dbo].[ConsoleServer] CHECK CONSTRAINT [FK_ConsoleServer_RackUnits]
I have these 2 questions:-
I know that the first line is responsible to create a FK between two DB tables. but what is the purpose of the following :
ALTER TABLE [dbo].[ConsoleServer] CHECK CONSTRAINT [FK_ConsoleServer_RackUnits]
In general, why does the DB script have the word GO. Now if I remove it the script will be executed well on the destination DB, so why it is included in the script prior to any statement?
The ALTER TABLE ... CHECK CONSTRAINT ... line enables the constraint. You can add a constraint and leave it disable (while you clean up the data for example). See more here
GO is a batch separator, it's only recognized by SSMS. Some statements, such as CREATE PROCEDURE... requires it to be the first statement in the batch. You can type it out in a new file, or use GO to terminate the previous batch. Don't send GO from your application through OLEDB or ADO.NET though.
I have a database which consist of 300 tables with data in it. I need to delete all the data inside each tables. I tried to truncate all tables but then I got an error that the process could not be completed because one of the column in a table is a foreign key. Is there other way to resolve my problem? Thanks.
You need to either:
remove all the foreign keys, truncate, then re-create FKs;
disable all the foreign keys, delete (not truncate), then re-enable FKs; or,
delete from child tables first.
The latter may not be possible if you're lucky enough to have circular references, and it can still be complicated even without circular references. The first two are also relatively complex, but I solved a very similar problem for a different user recently (and I find these easier than trying to determine the proper delete order):
Temporarily disable all foreign key constraints
Another idea is to perform a simpler and more complete wipe:
script the tables (and other objects obviously), drop the database and re-create it; or,
create a copy of the database, and use Visual Studio / SSDT or a 3rd party schema comparison tool to create all of the objects in the empty database (then you can drop the old database and rename the new one).
Try this : A quick way of doing it .sp_msforeachtable is an undocumented SP so there's a risk in using them. I came up with this answer using Aaron Logic by disabling the constraints used in his answer.
use [YourDB]
Go
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'Truncate Table ?'
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
People,
I need migrate a Oracle trigger to SQL server, but I could not do.
The trigger in Oracle is very simple:
CREATE OR REPLACE TRIGGER trigger_teste
BEFORE INSERT OR UPDATE
ON teste
FOR EACH ROW
DECLARE
BEGIN
:new.id := (coalesce(:NEW.id, 0));
:new.vlr_sal := (coalesce(:NEW.vlr_sal, 0.00));
END;
I tried several ways but none successfully!
Thank for help!
My T-SQL is a bit rusty, but something like this should work. Note that SQL server does not have row level triggers, only statement level triggers.
CREATE TRIGGER trigger_teste
ON teste
BEFORE INSERT OR UPDATE
AS
update inserted
set id = coalesce(id, 0),
vlr_sal = coalesce(vlr_sal, 0.0)
GO
(Not sure if I got missed a semicolon or not. I never understood when SQL Server needs or deosn't need one)
See the manual for more details:
http://msdn.microsoft.com/en-US/library/ms189799%28v=sql.90%29
http://msdn.microsoft.com/en-US/library/ms191300%28v=sql.90%29
This is not an appropriate use of triggers in any flavour of RDBMS. The SQL standard allows us to define default values when we create the table using the DEFAULT constraint syntax. Both Oracle and SQL Server have this.
Obviously you haven't do this when you created the table. The good news is we can use ALTER TABLE to add default constraints. Something like this
alter table teste
alter column id set default 0
That's for SQL Server. In Oracle it would be:
alter table teste
modify id default 0
As the nameless equine points out, a complete replacement for the trigger must include NOT NULL constraints on the affected columns. If the existing table lacks not null constraints we can add them using the same syntax as shown above, replacing the DEFAULT clause with NOT NULL - or even combining the two clauses in the same statement.
How can I truncate all tables of a database?
Why would you want to truncate all tables? If you want an empty database, why not run the CREATE script of the database?
If you want to Truncate a table referenced by a foreign key, you will have to drop the FK constraint first. Disabling constraints is something that is not possible anymore in recent versions of SQL Server.
You can see this post : how-do-you-truncate-all-tables-in-a-database-using-tsql
I use the script
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'DELETE FROM ?'
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
Reset Auto-Increment? I'm not sure if you understand correctly how this works.
Primary Key incrementing is handled by SQL Server using the IDENTITY specification. If your tables have got no data in them, it will always start from 0.
If I were you, I'd go have a flick through your programming books and pick up some basic database knowledge as it sounds like you're missing some fundamental facts there.
I've just moved a database from a SQL 2000 instance to a SQL 2008 instance and have encountered an odd problem which appears to be related to IDENTITY columns and stored procedures.
I have a number of stored procedures in the database along the lines of this
create procedure usp_add_something #somethingId int, #somethingName nvarchar(100)
with encryption
as
-- If there's an ID then update the record
if #somethingId <> -1 begin
UPDATE something SET somethingName = #somethingName
end else begin
-- Add a new record
INSERT INTO something ( somethingName ) VALUES ( #somethingName )
end
go
These are all created as ENCRYPTED stored procedures. The id column (e.g. somethingId in this example) is an IDENTITY(1,1) with a PRIMARY KEY on it, and there are lots of rows in these tables.
Upon restoring onto the SQL 2008 instance a lot of my database seems to be working fine, but calls like
exec usp_add_something #somethingId = -1, #somethingName = 'A Name'
result in an error like this:
Violation of PRIMARY KEY constraint 'Something_PK'. Cannot insert duplicate key in object 'dbo.something'.
It seems that something is messed up that either causes SQL Server to not allocate the next IDENTITY correctly...or something like that. This is very odd!
I'm able to INSERT into the table directly without specifying the id column and it allocates an id just fine for the identity column.
There are no records with somethingId = -1 ... not that that should make any difference.
If I drop and recreate the procedure the problem goes away. But I have lots of these procedures so don't really want to do that in case I miss some or there is a customized procedure in the database that I overwrite.
Does anyone know of any known issues to do with this? (and a solution ideally!)
Is there a different way I should be moving my sql 2000 database to the sql 2008 instance? e.g. is it likely that Detach and Attach would behave differently?
I've tried recompiling the procedure using sp_recompile 'usp_add_something' but that didn't solve the problem, so I can't simply call that on all procedures.
thanks for any help
R
(cross-posted here)
If the problem is an improperly set identity seed, you can reset a table this way:
DBCC CHECKIDENT (TableName, RESEED, 0);
DBCC CHECKIDENT (TableName, RESEED);
This will automatically find the highest value in the table and set the seed appropriately so you don't have to do a SELECT Max() query. Now fixing the table can be done in automation, without dynamic SQL or manual script writing.
But you said you can insert to the table directly without a problem, so it's probably not the issue. But I wanted to post to set the record straight about the easy way to reset the identity seed.
Note: if your table's increment is negative, or you in the past reset the seed to use up all negative numbers starting at the lowest after consuming all the positive numbers, all bets are off. Especially in the latter case (having a positive increment, but you are using identity values lower than others already in the table), then you do not want to run DBCC CHECKIDENT without specifying NORESEED ever. Because just DBCC CHECKIDENT (TableName); will screw up your identity value. You must use DBCC CHECKIDENT (TableName, NORESEED). Fun times will ensue if you forget this. :)
First, check the maximum ID from your table:
select max(id_column) from YourTable
Then, check the current identity seed:
select ident_seed('YourTable')
If the current seed is lower than the maximum, reseed the table with dbcc checkident:
DBCC CHECKIDENT (YourTable, RESEED, 42)
Where 42 is the current maximum.
Demonstration code for how this can go wrong:
create table YourTable (id int identity primary key, name varchar(25))
DBCC CHECKIDENT (YourTable, RESEED, 42)
insert into YourTable (name) values ('Zaphod Beeblebrox')
DBCC CHECKIDENT (YourTable, RESEED, 41)
insert into YourTable (name) values ('Ford Prefect') --> Violation of PRIMARY KEY
I tried and was unable to replicate this on another server.
However, on my Live servers I dropped the problem database from sql 2008 and recreated it using a detach and reattach and this worked fine, without these PRIMARY KEY VIOLATION errors.
Since I wanted to keep the original database live, in fact my exact steps were:
back up sourceDb and restore as sourceDbCopy on the same instance
take sourceDbCopy offline
move the sourceDbCopy files to the new server
attach the database
rename the database to the original name
If recreating the procedures helps, here's an easy way to generate a recreation script:
Right click database -> Tasks -> Generate scripts
On page 2 ("Choose Objects") select the stored procedures
On page 3 ("set scripting options") choose Advanced -> Script DROP and CREATE and set it to Script DROP and CREATE.
Save the script somewhere and run it