SQL Server - Schrödinger's View - sql-server

I can't create/alter a VIEW because it already exists.
I also can't drop the same VIEW because it does not exists!
First of all, I'm SA on a SQL Server 2012.
CREATE VIEW [dbo].[some_name]
There is already an object named 'some_name' in the database.
DROP VIEW [dbo].[some_name]
Cannot drop the view 'dbo.some_name', because it does not exist or you
do not have permission.
SELECT OBJECT_ID(N'dbo.some_name', N'V')
SELECT OBJECT_ID('dbo.some_name', 'V')
SELECT OBJECT_ID(N'dbo.some_name')
SELECT OBJECT_ID('dbo.some_name')
SELECT OBJECT_ID(N'some_name')
SELECT OBJECT_ID('some_name')
NULL (for each query)
SELECT * FROM sys.objects WHERE name LIKE '%some_name%'
SELECT * FROM sys.objects WHERE name ='some_name'
SELECT * FROM sys.objects WHERE name = N'some_name'
empty result (for each query)
SELECT * FROM fn_my_permissions(N'dbo.some_name','OBJECT')
SELECT * FROM fn_my_permissions('dbo.some_name','OBJECT')
SELECT * FROM fn_my_permissions(N'some_name','OBJECT')
SELECT * FROM fn_my_permissions('some_name','OBJECT')
SELECT * FROM fn_my_permissions(N'some_name','VIEW')
SELECT * FROM fn_my_permissions('some_name','VIEW')
empty result (for each query)
Alt+F1 on 'some_name':
The object 'some_name' does not exist in database 'X' or is invalid
for this operation.
EXEC sp_rename
#objname = 'other_name',
#newname = 'some_name'
Error: The new name 'some_name' is already in use as a object name and
would cause a duplicate that is not permitted.
EXEC sp_rename
#objname = 'some_name',
#newname = 'other_name'
No item by the name of 'some_name' could be found in the current
database 'X', given that #itemtype was input as '(null)'.
And now something interesting. If I run:
DROP FUNCTION [dbo].[some_name]
DROP SYNONYM [dbo].[some_name]
DROP TABLE [dbo].[some_name]
DROP TRIGER[dbo].[some_name]
DROP TYPE [dbo].[some_name]
DROP VIEW [dbo].[some_name]
I get only 5 messages:
Cannot drop the [FUNCTION, SYNONYM, TABLE, TRIGGER, TYPE]
'dbo.some_name', because it does not exist or you do not have
permission. (no mention of the VIEW)
But if I move the View command to the top :
DROP VIEW [dbo].[some_name]
DROP FUNCTION [dbo].[some_name]
DROP SYNONYM [dbo].[some_name]
DROP TABLE [dbo].[some_name]
DROP TRIGER[dbo].[some_name]
DROP TYPE [dbo].[some_name]
I get 6 messages, as expected.
Please help.
UPDATE
After a few CHECKDB commands I found what seems to be the problem. As suspected, this view is in an unconsistend state. By the DBCC command log I got the object_id of it. It does not existis on sys.objects, but it does existis on sys.columns. So, there are a few orphan columns on my database, which indicates a failure when creating or dropping this object.
So, by running DBCC CHECKCATALOG (and a few other DBCC commands) I got the messages:
Msg 3853, State 1: Attribute
(referenced_major_id=859202161,referenced_minor_id=42) of row
(class=0,object_id=990678627,column_id=0,referenced_major_id=859202161,referenced_minor_id=42)
in sys.sql_dependencies does not have a matching row
(object_id=859202161,column_id=42) in sys.columns.
Msg 8956, Level 16, State 1, Line 1 Index row (1:123:12) with values
(nsclass = 0 and nsid = 1 and name = 'some_name') points to the data
row identified by (RID = (1:456:45)).
SOLUTION
0 - Backup your database.
1 - Reboot your server on Single User Mode (-m parameter)
2 - Set the database to Single User Mode:
ALTER DATABASE X
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
GO
3 - Run a CHECKDB command with a repair option. In my case it was:
DBCC CHECKDB (X,REPAIR_REBUILD)
4 - Set the database back to Multi User Mode
ALTER DATABASE X
SET MULTI_USER
WITH ROLLBACK IMMEDIATE;
GO
'X' is the name of the database.
I'm not sure if step 0 and 1 are really necessary, but better safe than sorry.
You may find more info about the CHECKDB command and its repair otions at: DBCC CHECKDB

I think SQL server requires that object names be unique. You certainly cannot have a table and a view with the same name, as it would be impossible to distinguish which object was intended when you refer to it. But I think function and procedure names also have to be unique ( and this may not be strictly necessary, as far as I know the context in which these names are used always allows them to be distinguished ).

From your error messages, I understand that dbo.some_name exists, but, you don't have enough permissions to view dbo.some_name.
sys.objects will show only the objects, to which you have got permission to view .MSDN reference
Permissions
The visibility of the metadata in catalog views is limited
to securables that a user either owns or on which the user has been
granted some permission.
You can see what permissions you have got on an object by running the below query:
SELECT * FROM fn_my_permissions('dbo.some_name','OBJECT')
You need to have CONTROL permission to drop it. You need to have ALTER permission to rename the object.
UPDATE
can you please again check whether you are part of sysadmin role at server level and part of db_owner role at db level (sysadmins enter database as db_owners).
use database_name
go
SELECT Is_srvrolemember('sysadmin')
select IS_ROLEMEMBER('db_owner')

Related

There is already an object named 'name' in the database - stored procedure error - SQL Server

I have two tables called timeus and usdpay in my SQL Server database. These two tables get updated every week.
I did small transformation and combined these two tables and created a new table called fluslabor.
I created fluslabor using the stored procedure shown here, and it is working:
CREATE PROCEDURE [dbo].[sp_uslabor]
AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID(N'dbo.fluslabor', N'U') IS NOT NULL
TRUNCATE TABLE [dbo].[fluslabor];
SELECT ut.employee_code
,ut.employee_name
,ut.department_desc
,ut.location_desc
,ut.hour
,ut.projects_code
,ut.in_effective_time
,ut.out_effective_time
,ut.date
,ut.id
,p.rate
,(p.rate * ut.hour ) as Labour_Cost
INTO fluslabor
FROM timeus ut
LEFT JOIN usdpay p ON (TRIM(ut.id) = TRIM(p.id) AND ut.date = p.date)
WHERE ut.projects_code NOT LIKE '0%'
END
Today I got new data updated in my two tables timeus and usdpay.
When I execute my stored procedure, SQL Server is throwing this error:
Msg 2714, Level 16, State 6, Procedure SP_uslabor, Line 12 [Batch Start Line 38]
There is already an object named 'fluslabor' in the database.
I need to truncate my table every time and load the new data. I checked the similar post, they said to use drop table option. I don't want to drop the table, just want to truncate and execute the procedure
Can anyone advise what is the issue here please?
The problem here is that the table fluslabor already exists in the database. what you are trying above the insert is checking the object existence and then truncating the same
There are two possible approaches that you can try here.
Instead if the TRUNCATE do a DROP TABLE. But This will also remove the existing user permissions on the table if you have provided specific custom access to the table to any of the users
IF OBJECT_ID(N'dbo.fluslabor', N'U') IS NOT NULL DROP TABLE [dbo].[fluslabor];
The safest approach will be change the SELECT .. INTO statement and convert it into INSERT INTO like this
INSERT INTO fluslabor ( <List your Destination columns> ) SELECT <List your Source columns> FROM <Source Query>
the 2nd approach will have the records loaded along with keeping all the existing permissions
IF EXISTS (SELECT 1 FROM sys.objects WHERE type = 'P' AND name = 'your SP name')
BEGIN
DROP PROCEDURE "your SP name";
END
GO
CREATE PROCEDURE "your SP name"
AS
BEGIN
.
.
.
.
try this one I guess this will help you.

Clone a database with sample data in table

I want a script that will quickly delete a Test instance of a database and recreate it with only a sample of rows in each table. I know there is no referential integrity issues or other object restraints such as stored procedures linked to records. I have tried the following but it states database in use. I think I am missing something in between the drop and clone. What am I doing wrong here? Or does this have to be split between two scripts?
-- ensure "master" is selected in SSMS
IF EXISTS(select * from sys.databases where name='shoesales_TEST')
ALTER DATABASE shoesales_TEST set single_user with rollback immediate
GO
IF EXISTS(select * from sys.databases where name='shoesales_TEST')
DROP DATABASE shoesales_TEST
GO
DBCC CLONEDATABASE
(
shoesales
, shoesales_TEST
)
GO
ALTER DATABASE shoesales_TEST SET READ_WRITE
GO
USE shoesales_TEST
GO
INSERT INTO shoesales_TEST.dbo.sizesales
SELECT TOP 30 * FROM shoesales.dbo.sizesales
GO

Sybase - How to create read-only user only can SELECT all tables?

I need to create an user which only can SELECT all tables in Sybase database.
The way is :
1. Create role which can SELECT all tables.
2. Grant role to this user.
My Sybase version is : Adaptive Server Enterprise/15.0.2
create a readonly role
grant only the select permission to the new role
add the user to that role
While the other answer is technically correct, it omits a crucial detail: you cannot simply grant the permissions for all tables to a single user or group - you have to specify all table (and procedure, view etc.) names yourself. Wildcards do not work and result in generic and not very helpful Error -131: Syntax error messages.
I've adapted a very good workaround by marc_s from SQL Server 2008 for Sybase (tested on SYL Anywhere, but should work on ASE too, if the documentation is correct).
It could of course be improved to be fully automatic and account for changed tables, but if you just want to quickly give some users read-only access to a relatively static database (be it the sales department or an application), then this just works well enough:
Create a user (you could also create a group with CREATE ROLE):
CREATE USER readonly IDENTIFIED BY 'secretpassword';
Check which tables you need to include (if you want to exclude the system tables, for example). To do that, look into systable for all tables/views/procedures and sysuserperm for user details:
SELECT
t.table_id,
t.table_name,
t.table_type,
t.creator,
u.user_name
FROM systable AS t
JOIN sysuserperm AS u ON t.creator = u.user_id
ORDER BY t.table_id ASC;
Depending on your data and needs, you can modify the query to just return the table_names that you need. In this example we get all views and tables that are owned by DBA (owner = schema). Now create the GRANT statements:
SELECT
t.table_name,
GrantCmd = 'GRANT SELECT ON dba.' + t.table_name + ' TO readonly;',
RevokeCmd = 'REVOKE SELECT ON dba.' + t.table_name + ' FROM readonly;'
FROM systable AS t
WHERE t.creator = 1
AND (t.table_type = 'BASE' OR t.table_type = 'VIEW');
Copy the resulting statements, wrap them in a transaction and execute it:
BEGIN TRANSACTION;
GRANT SELECT ON dba.table1 TO readonly;
GRANT SELECT ON dba.table2 TO readonly;
GRANT SELECT ON dba.table3 TO readonly;
<...>
COMMIT TRANSACTION;
Now you can execute SELECT statements. You have to manually add the context to the tables though:
SELECT * from table1; -- Error -141: table not found
SELECT * from dba.table1; -- works as expected
DELETE FROM dba.table1; -- Error -121: permission denied
If you want to revoke access, just use the revoke part from before.

How to add a new schema to sql server 2008?

How do you add a new schema to a database? I am creating a new table and would like to select my own schema from the properties list, but I don't know how to create it. I am using SQL Server Management 2008.
Use the CREATE SCHEMA syntax or, in SSMS, drill down through Databases -> YourDatabaseName -> Security -> Schemas. Right-click on the Schemas folder and select "New Schema..."
Here's a trick to easily check if the schema already exists, and then create it, in it's own batch, to avoid the error message of trying to create a schema when it's not the only command in a batch.
IF NOT EXISTS (SELECT schema_name
FROM information_schema.schemata
WHERE schema_name = 'newSchemaName' )
BEGIN
EXEC sp_executesql N'CREATE SCHEMA NewSchemaName;';
END
I use something like this:
if schema_id('newSchema') is null
exec('create schema newSchema');
The advantage is if you have this code in a long sql-script you can always execute it with the other code, and its short.
Best way to add schema to your existing table: Right click on the specific table-->Design -->
Under the management studio Right sight see the Properties window and select the schema and click it, see the drop down list and select your schema. After the change the schema save it. Then will see it will chage your schema.
You can try this:
use database
go
declare #temp as int
select #temp = count(1) from sys.schemas where name = 'newSchema'
if #temp = 0
begin
exec ('create SCHEMA temporal')
print 'The schema newSchema was created in database'
end
else
print 'The schema newSchema already exists in database'
go
In SQL Server 2016 SSMS expand 'DATABASNAME' > expand 'SECURITY' > expand 'SCHEMA' ; right click 'SCHEMAS' from the popup left click 'NEW SCHEMAS...' add the name on the window that opens and add an owner i.e dbo click 'OK' button

Drop multiple procedures (SQL2005)

I am curious whether I can drop multiple procedures by simple using "%"?
Like:
DROP constantName%
When I use DROP in the Management studio, it looks like that:
/****** Object: StoredProcedure [dbo].[x] Script Date: 02/02/2010 09:36:25 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[x]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[x]
Why it is checking the object ID when I am dropping this particular object?
The OBJECT_ID returns the database object identification number of a schema-scoped object. In your code it is checking it inside an IF EXISTS, so that it will only DROP the stored proc if is present in the database.
You could just have DROP PROCEDURE proc_name, but you could end up getting an error if the procedure does not exist. Its just good practise to check before you remove.
Tables, View, Stored Procs etc all have an OBJECT_ID as a key identifier.
I do not believe you can drop mutiple stored procedures using a LIKE. (Though i;m not 100% certain on that)
I think SQL was designed with this limitation, the drop procedure command needs a string constant. You can't pass a variable as an argument either, it just gives a 'incorrect syntax' error when you do.
Also the OBJECT_ID function only returns a valid id of objects the user owns, or has permission to. So OBJECT_ID is used because it performs the security validation.
Deleting with just "WHERE name = 'object_name'" could also work, but only if the user has permission for that object.
I am afraid you cant use the like syntax in DROP, below the simple one liner to drop multiple procedures.
DROP PROCEDURE testest,testest1
And for your 2nd question. There are scenarious we can create Storedprocedure that can be accessible only to the particular role.
create proc dbo.testest
as
begin
select 1
end
query sys.objects with the role value
select * from sys.objects where name ='dbo.testest'
it returns null
select * from sys.objects where name ='testest'
now it works
sys.objects catalog view stores the information without the role names (only just names). But using OBJECT_ID, we can retrieve the role specific info
select OBJECT_ID('dbo.testest') //works
select OBJECT_ID('testest') //works
hope you can understand now.

Resources