I have a lot of code I am trying to run where I'm querying the sysobjects table to check if an object exists before I drop it and create it again.
Issue being, sometimes if I go:
if not exists (select name from sysobjects o where o.name = 'my_table' and o.type = 'U')
CREATE TABLE my_table (..)
go
it works, no worries. However, when I came back to run it again, I get this lovely error:
SQL Server Error on (myserver) Error:2714 at Line:10 Message:There is already an object named 'my_table' in the database.
Thanks for that, SQL Programmer. I actually asked for you not to create this table if it already exists. -_-
Any ideas?
the logic to what you are doing doesn't seem quite right. based on your statement:
"I am trying to run where I'm querying the sysobjects table to check if an object exists before I drop it and create it again"
you should simply do a delete followed by a create. This way is usually better because it ensures that the table will be updated. if the table existed and you had changes, you are probably not getting what you want.
The immediate issue you are running into is an assumed db ownership that was not consistent between runs.
based on your clarification below - here is what you can do:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[XXXX]') AND type in (N'U'))
DROP TABLE [dbo].[XXXX]
GO
CREATE TABLE [dbo].[XXXX(...
GO
you can run this over and over again...
The sybase parsers object validation pass is global and not based on conditional evaluation. Even though your code can not execute CREATE TABLE the statement is still checked for syntax and applicability which fails when the system sees that the table already exists.
The only way around this that I know of is to put your create statements inside of an EXEC() which would be evaluated only if the section was executed.
yes, the entire batch of SQL is normalized and compiled so as to create an "execution plan" for the entire batch. During normalization, the "possible" "create table" statement is a problem if it already exists at compile time.
My solution: rename -
if exists (select 1 from ....)
begin
drop table xyz
create table xyz_zzzz ( ... )
exec sp_rename 'xyz_zzzz','xyz'
end
Related
During debugging the tsqlt code, I have directly run the below statement without wrapping it as sp and my original table constraint got deleted and some data missing from the original table.
Exec tSQLt.FakeTable #TableName = N'DBO.Employee', #Identity=1;
Exec tSQLt.FakeTable #TableName = N'DBO.Salary', #Identity=1;
How do I prevent running faketable statement in tsqlt is impacting the original table?
There is no way to prevent executing tSQLt.FakeTable outside of the framework. There are also good reasons to not prevent that, so I do not think that adding that functionality is the right approach.
However, if you’re using the newest version of tSQLt, you can use tSQLt.UndoTestDoubles to get the original object(s) back.
Ugh, been there... You can't prevent it, short of contributing to the project and putting a pull request in to add the functionality.
FakeTable creates a backup of your original table so you should be able to get the original table back. These backup table names start with tSQLt.tempobject and end in an identifier. You can delete the new "fake" table (which now has the name of your original table) and rename the tempobject table if/when you find it.
Something I've done in the past is to query for a column that I know is in the table to find the name of the tSQLt table:
SELECT t.name
FROM sys.columns c
INNER JOIN sys.tables t ON t.object_id = c.object_id
WHERE c.name = 'SomeCol';
I have a table that is the result of an INNER JOIN and then to that table I have to a apply a bunch of queries, so at the end the whole code in SQL is really big and in the future (and that's the main problem) I will have problems to understand what did I do.
So for this reason I am considering the possibility of creating views, so in each step I have a view created and I know what does each one of the queries.
So with that goal I started to use IF ELSE statements to create views if they dont' exist etc. but I'm stumbling with a lot of errors and problems.
First of all, this is the way I'm creating a view with the IF statement:
-- This portion of code is common in all the views
IF NOT EXISTS
(
SELECT 1
FROM sys.views
WHERE Name = 'NAME_OF_THE_VIEW'
)
BEGIN
EXEC('CREATE VIEW NAME_OF_THE_VIEW AS SELECT 1 as Val')
END
GO
ALTER VIEW NAME_OF_THE_VIEW
AS
-- Here I put the query of the view
SELECT *
FROM table_1
When I execute this code it works, but the SQL Server Management Studio underlines "NAME_OF_THE_VIEW" in the ALTER VIEW statement and when I hover the mouse it says: Invalid object name 'NAME_OF_THE_VIEW'. I don't understand why if there's a supposed error it still works.
The other problem is that when I introduce more code like the code above in order to create other views in the same script, the whole ALTER VIEW statement is underlined and when I hover this message appears; Incorrect syntax: 'ALTER VIEW' must be the only statement in the batch.
So the question is: hoy can I put everything in the same script, where I can create views to avoid doing a lot of subqueries, and without getting this errors? The SQL-Server version is 15.
So the question is: hoy can I put everything in the same script, where I can create views to avoid doing a lot of subqueries, and without getting this errors?
There's no need to check for existence of the view. Just CREATE OR ALTER VIEW
CREATE OR ALTER VIEW NAME_OF_THE_VIEW
AS
-- Here I put the query of the view
SELECT *
FROM table_1
GO
CREATE OR ALTER VIEW NAME_OF_THE_OTHER_VIEW
AS
-- Here I put the query of the view
SELECT *
FROM table_1
I am stuck with the following stored procedure where I can't seem to get the IF EXISTS and DROP parts to work, leading to a failure in the SELECT INTO part.
Both database A and database B are on the same server, I have full permissions in both databases. The stored procedure is in database A.
I have copied the IF EXISTS syntax from somewhere (can't remember where) so I don't really understand the structure of it. I gathered the problem lies in the IF EXISTS statement because when I try and execute IF EXISTS component of the stored procedure, I get something if I have selected DatabaseB in the top left-hand corner drop-down box in Management Studio but if I have DatabaseA selected in there, I get nothing.
I have also tried to run similarly structured stored procedures in DatabaseA (where there is an IF EXISTS and DROP statements pointing to DatabaseB followed by a SELECT INTO from DatabaseA into DatabaseB) and I have got some to work before, while some others failed. I cant seem to pinpoint what is causing it to work sometimes and sometimes not.
USE [DatabaseA]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--DROP TABLE A if exists--
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'DatabaseB.dbo.TableA') AND type IN (N'U'))
DROP TABLE DatabaseB.dbo.TableA
--Select INTO TableA on DatabaseB--
SELECT *
INTO DatabaseB.dbo.TableA
FROM DatabaseA.dbo.TableA
I usually use if object_id('databaseB.dbo.TableA') is not null instead of the exists check to avoid having to fully qualify sys.objrcts.
I understand that you cannot simply drop an SQL server schema, you must first of all drop all the objects contained therein. I found this stored proc that performs the task of dropping all objects and then the schema itself.
Is there really no simpler way to drop a schema? Ideally, I'd like to find a way to do this without using a stored proc.
Also, it seems like the stored proc will cause errors if the schema name provided does not exist. I would like it to simply do nothing instead. I guess this is simply a matter of putting this pseudocode at the top of the script
IF #SchemaName NOT EXISTS
QUIT
Can someone convert this into language that SQL Server will understand?
The following at the top of the script should help:
IF SCHEMA_ID(#SchemaName) IS NULL
RETURN
SCHEMA_ID returns the schema ID associated with a schema name, and RETURN exits unconditionally from a query or procedure.
You have to remove all objects in the schame before dropping it or migrate all objects to a new schema. There is no "wildcard" option for either
To exit a stored procedure before any further processing...
IF SCHEMA_ID(#SchemaName) IS NULL
RETURN
if exists(select * from sys.schemas where name = #SchemaName)
begin
-- Your work
end
You must drop all objects before dropping the schema.
To check if a schema exists:
IF NOT EXISTS (select SCHEMA_NAME from INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='YOUR DB NAME HERE' and SCHEMA_NAME=#SchemaName)
BEGIN
-- Do some processing...
return
END
How can I perform this query on whatever way:
delete from sys.tables where is_ms_shipped = 0
What happened is, I executed a very large query and I forgot to put USE directive on top of it, now I got a zillion tables on my master db, and don't want to delete them one by one.
UPDATE: It's a brand new database, so I don't have to care about any previous data, the final result I want to achieve is to reset the master db to factory shipping.
If this is a one-time issue, use SQL Server Management Studio to delete the tables.
If you must run a script very, very carefully use this:
EXEC sp_msforeachtable 'DROP TABLE ?'
One method I've used in the past which is pretty simple and relatively foolproof is to query the system tables / info schema (depending on exact requirements) and have it output the list of commands I want to execute as the results set. Review that, copy & paste, run - quick & easy for a one-time job and because you're still manually hitting the button on the destructive bit, it's (IMHO) harder to trash stuff by mistake.
For example:
select 'drop table ' + name + ';', * from sys.tables where is_ms_shipped = 0
No backups? :-)
One approach may be to create a Database Project in Visual Studio with an initial Database Import. Then delete the tables and synchronize the project back to the database. You can do the deletes en masse with this approach while being "buffered" with a commit phase and UI.
I am fairly certain the above approach can be used to take care of the table relationships as well (although I have not tried in the "master" space). I would also recommend using a VS DB project (or other database management tool that allows schema comparing and synchronization) to make life easier in the future as well as allowing version-able (e.g. with SCM) schema change-tracking.
Oh, and whatever is done, please create a backup first. If nothing else, it is good training :-)
Simplest and shortest way I did was this:
How to Rebuild System Databases in SQL Server 2008
The problem with all other answers here is that it doesn't work, since there are related tables and it refuses to execute.
This one, not only it works but actually is what I am looking for: "Reset to factory defaults" as stated in the question.
Also this one will delete everything, not only tables.
This code could be better but I was trying to be cautious as I wrote it. I think it is easy to follow an easy to tweak for testing before you commit to deleting your tables.
DECLARE
#Prefix VARCHAR(50),
#TableName NVARCHAR(255),
#SQLToFire NVARCHAR(350)
SET #Prefix = 'upgrade_%'
WHILE EXISTS(
SELECT
name
FROM
sys.tables
WHERE
name like #Prefix
)
BEGIN
SELECT
TOP 1 --This query only iterates if you are dropping tables
#TableName = name
FROM
sys.tables
WHERE
name like #Prefix
SET #SQLToFire = 'DROP TABLE ' + #TableName
EXEC sp_executesql #SQLToFire;
END
I did something really similar, and what I wound up doing was using the Tasks--> script database to only script drops for all the database objects of the originally intended database. Meaning the database I was supposed to run the giant script on, which I did run it on. Be sure to include IF Exists in the advanced options, then run that script against the master and BAM, deletes everything that exists in the original target database that also exists in the master, leaving the differences, which should be the original master items.
Not very elegant but as this is a one time task.
WHILE EXISTS(SELECT * FROM sys.tables where is_ms_shipped = 0)
EXEC sp_MSforeachtable 'DROP TABLE ?'
Works fine on this simple test (clearing a on the second loop after failing on the first attempt and proceeding onwards to delete b)
create table a
(
a int primary key
)
go
create table b
(
a int references a (a)
)
insert into a values (1)
insert into b values (1)