Deleting Extended Properties of a column - sql

I have a database where I put comments in the Description property of many columns in my tables to describe the columns. The Description property apparently is implemented as an Extended Property named MS_Description.
Now I need to copy the database to SQL Azure, that does not permit Extended Properties. What is the Transact SQL commands available to search every column for the Extended Property MS_Description and delete it.

Here you have a detailed explanation on how to list extended properties on SQL Server 2008R2.
Then at the end of that page you have several references, one of them is to the sp_dropextendedproperty. Make use of it at will.
One blog with useful information and detailed samples.
Here you have a code sample to show all extended properties for columns in a table:
USE AdventureWorks2008R2;
GO
SELECT major_id, minor_id, t.name AS [Table Name],
c.name AS [Column Name],
value AS [Extended Property]
FROM sys.extended_properties AS ep
INNER JOIN sys.tables AS t ON ep.major_id = t.object_id
INNER JOIN sys.columns AS c ON ep.major_id = c.object_id
AND ep.minor_id = c.column_id
WHERE class = 1;
GO
Even more samples here

These sentences were useful to me:
-- find the property of a specific column
SELECT * FROM SYS.EXTENDED_PROPERTIES
WHERE [major_id] = OBJECT_ID('My_Table')
AND [name] = N'MS_Description'
AND [minor_id] = (SELECT [column_id], * FROM SYS.COLUMNS
WHERE [name] = 'My_Column' AND [object_id] = OBJECT_ID('My_Table') )
-- find a random property in all columns in a table (useful when a column was deleted but the property was left behind)
SELECT * FROM SYS.EXTENDED_PROPERTIES
WHERE [major_id] = OBJECT_ID('My_Table')
AND [name] = N'MS_Description'
AND CAST([value] AS VARCHAR(MAX)) LIKE '%"Nombre": "My_Column"%'
-- drop extended properties from an existing column
IF EXISTS (
SELECT 1 FROM SYS.EXTENDED_PROPERTIES
WHERE [major_id] = OBJECT_ID('My_Table')
AND [name] = N'MS_Description'
AND [minor_id] = (SELECT [column_id], * FROM SYS.COLUMNS
WHERE [name] = 'My_Column' AND [object_id] = OBJECT_ID('My_Table') )
)
BEGIN
EXECUTE sp_dropextendedproperty #name = N'MS_Description',
#level0type = N'SCHEMA',
#level0name = N'dbo',
#level1type = N'TABLE',
#level1name = N'My_Table',
#level2type = N'COLUMN',
#level2name = N'My_Column';
END

Related

How to check all stored procedures which update a specific column

Following is the sample to search stored procedures which have the keyword Student in them:
SELECT TOP (1000) *
FROM [eUniversityManagement].[sys].[all_sql_modules]
WHERE definition LIKE '%Student%'
I just wondering can we search any stored procedure that has and UPDATE on Student.name for example:
UPDATE STUDENT
SET Name = #Name,
Address = #Address,
DOB = #DOB
WHERE id = #StudentID
Thanks.
You can use the sys.dm_sql_referenced_entities function for this. It's a little complicated, as it wants the procedure name which references the column, so you need to start off with all objects and apply the functions
SELECT o.name, schema_name = s.name
FROM sys.objects o
JOIN sys.schemas s ON s.schema_id = o.schema_id
CROSS APPLY sys.dm_sql_referenced_entities (QUOTENAME(s.name) + '.' + QUOTENAME(o.name), 'OBJECT') r
WHERE o.type IN ('P', 'TR')
AND r.referenced_entity_name = 'student'
AND r.referenced_minor_name = 'Name'
AND r.is_updated = 1;

Get a list of database users and his/her permission right from SQL Server

I need to get a report which will show database users and his/her permission on SQL Server. Below is the query that will do the job.
WITH CTE AS
(
SELECT
[UserName] = CASE princ.[type]
WHEN 'S' THEN princ.[name]
WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
END,
[UserType] = CASE princ.[type]
WHEN 'S' THEN 'SQL User'
WHEN 'U' THEN 'Windows User'
END,
[DatabaseUserName] = princ.[name],
[Role] = null,
[PermissionType] = perm.[permission_name],
[PermissionState] = perm.[state_desc],
[ObjectType] = obj.type_desc,--perm.[class_desc],
[ObjectName] = OBJECT_NAME(perm.major_id),
[ColumnName] = col.[name]
FROM
--database user
sys.database_principals princ
LEFT JOIN
--Login accounts
sys.login_token ulogin on princ.[sid] = ulogin.[sid]
LEFT JOIN
--Permissions
sys.database_permissions perm ON perm.[grantee_principal_id] = princ.[principal_id]
LEFT JOIN
--Table columns
sys.columns col ON col.[object_id] = perm.major_id
AND col.[column_id] = perm.[minor_id]
LEFT JOIN
sys.objects obj ON perm.[major_id] = obj.[object_id]
WHERE
princ.[type] in ('S','U')
UNION
--List all access provisioned to a sql user or windows user/group through a database or application role
SELECT
[UserName] = CASE memberprinc.[type]
WHEN 'S' THEN memberprinc.[name]
WHEN 'U' THEN ulogin.[name] COLLATE Latin1_General_CI_AI
END,
[UserType] = CASE memberprinc.[type]
WHEN 'S' THEN 'SQL User'
WHEN 'U' THEN 'Windows User'
END,
[DatabaseUserName] = memberprinc.[name],
[Role] = roleprinc.[name],
[PermissionType] = perm.[permission_name],
[PermissionState] = perm.[state_desc],
[ObjectType] = obj.type_desc,--perm.[class_desc],
[ObjectName] = OBJECT_NAME(perm.major_id),
[ColumnName] = col.[name]
FROM
--Role/member associations
sys.database_role_members members
JOIN
--Roles
sys.database_principals roleprinc ON roleprinc.[principal_id] = members.[role_principal_id]
JOIN
--Role members (database users)
sys.database_principals memberprinc ON memberprinc.[principal_id] = members.[member_principal_id]
LEFT JOIN
--Login accounts
sys.login_token ulogin on memberprinc.[sid] = ulogin.[sid]
LEFT JOIN
--Permissions
sys.database_permissions perm ON perm.[grantee_principal_id] = roleprinc.[principal_id]
LEFT JOIN
--Table columns
sys.columns col on col.[object_id] = perm.major_id
AND col.[column_id] = perm.[minor_id]
LEFT JOIN
sys.objects obj ON perm.[major_id] = obj.[object_id]
)
SELECT * FROM CTE
The problem of this query is I need to manually run this statement by databases, if I have 10 databases on SQL Server then I need to run 10 times to get report from different databases.
Now I thinking to automate this job, what I'm think is to get list of databases from sql server by below sql statement.
SELECT name
FROM master.dbo.sysdatabases
and pass these results to store procedures. But I'm stuck at there, any help are much appreciated.
There are several ways how you can achieve this.
1) EXEC sp_MSforeachdb #command
You can use such command to run your query on each database on your server. Example here.
2) Cursor
You can also use Cursor, example here.
3) Dynamic SQL
Last option is IMO rewriting your query into Dynamic SQL. Example here.
It all depends how exactly this should work, what should be the result - one table with stored results or just see the results in SSMS.

Looping through different tables of different dates

We have a legacy application which created multiple tables with the following naming convention: table_20140618, table_20140623, etc where the date is when the program run. I am trying to clean up the database now, and drop some of these tables.
In each table there are two fields: DateStarted and DateFinished. I want to select the tables (and then drop them) where DateStarted has value and DateFinished is NOT null.
At the moment I am using the following query to select all the tables that start with 'table_'
such as:
Select (TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME LIKE 'table_%';
I am not sure how to get all the tables together by searching within their fields. I could do it through the code, but that should mean multiple hits on the database. Any ideas?
Made this after my first comment above, but you should be able to alter the code to fit your specs. Basically, this will use dynamic SQL to generate the commands based on your filters and conditions. So you can use whatever conditions you want in the SELECT #SQL = ... part, to check for the dates, and then add the table name when the conditions are met.
The script returns a list with tablenames and the drop command, so you can check what you're doing before you do it. But from there you can just copy the drop command list and execute it if you want.
IF OBJECT_ID('tempdb..#TABLES') IS NOT NULL
DROP TABLE #TABLES
CREATE TABLE #TABLES (ROWNMBER INT IDENTITY(1,1), TABLENAME VARCHAR(256) COLLATE DATABASE_DEFAULT)
/*
-- Old code to fetch ALL tables with specified name
INSERT INTO #TABLES
SELECT name
FROM sys.tables
WHERE name LIKE 'table[_]%'
*/
-- Updated code to fetch only those tables which contain the DateStarted and DateFinished columns
INSERT INTO #TABLES
SELECT TAB.name
FROM sys.tables TAB
LEFT JOIN sys.columns C1 on C1.object_id = TAB.object_id
AND C1.name = 'DateStarted'
LEFT JOIN sys.columns C2 on C2.object_id = TAB.object_id
AND C2.name = 'DateFinished'
WHERE TAB.name LIKE 'table[_]%'
AND C1.name IS NOT NULL AND C2.name IS NOT NULL
IF OBJECT_ID('tempdb..#DROPPABLE_TABLES') IS NOT NULL
DROP TABLE #DROPPABLE_TABLES
CREATE TABLE #DROPPABLE_TABLES (TABLENAME VARCHAR(256) COLLATE DATABASE_DEFAULT)
DECLARE #ROW_NOW INT, #ROW_MAX INT, #SQL VARCHAR(MAX), #TABLENAME VARCHAR(256)
SELECT #ROW_NOW = MIN(ROWNMBER), #ROW_MAX = MAX(ROWNMBER) FROM #TABLES
WHILE #ROW_NOW <= #ROW_MAX
BEGIN
SELECT #TABLENAME = TABLENAME FROM #TABLES WHERE ROWNMBER = #ROW_NOW
SELECT #SQL =
'IF (SELECT COUNT(*) FROM '+#TABLENAME+' WHERE DateStarted IS NOT NULL) > 0
AND (SELECT COUNT(*) FROM '+#TABLENAME+' WHERE DateFinished IS NOT NULL) > 0
SELECT '''+#TABLENAME+''''
INSERT INTO #DROPPABLE_TABLES
EXEC(#SQL)
SET #ROW_NOW = #ROW_NOW+1
END
SELECT *, 'DROP TABLE '+TABLENAME DROPCOMMAND FROM #DROPPABLE_TABLES
EDIT:
As per your comment, it seems not all such tables have those columns. You can use the following script to identify said tables and which column is missing, so you can check into them further. And you can use the same idea to filter the results of the first query to only count in tables which have those columns.
SELECT TAB.name TABLENAME
, CASE WHEN C1.name IS NULL THEN 'Missing' ELSE '' END DateStarted_COL
, CASE WHEN C2.name IS NULL THEN 'Missing' ELSE '' END DateFinished_COL
FROM sys.tables TAB
LEFT JOIN sys.columns C1 on C1.object_id = TAB.object_id
AND C1.name = 'DateStarted'
LEFT JOIN sys.columns C2 on C2.object_id = TAB.object_id
AND C2.name = 'DateFinished'
WHERE TAB.name LIKE 'table[_]%'
AND (C1.name IS NULL
OR C2.name IS NULL)

SQLServer - How to find dependent tables on my table?

Using SQLServer :
I have a table user :
id
name
email
There are some other tables (about 200 more tables), some of which use user.id as foreign key on cascade delete.
So, I want to find out - Which tables use this foreign key (user.id) ?
I am accessing my sql-server with SQL Server Management Studio.
The way to get ONLY TABLE references (i.e. tables that uses given table as a foreign key and tables that given table uses the same way) you can use this code snippet:
declare #tableName varchar(64);
set #tableName = 'TABLE';
select
SO_P.name as [parent table]
,SC_P.name as [parent column]
,'is a foreign key of' as [direction]
,SO_R.name as [referenced table]
,SC_R.name as [referenced column]
,*
from sys.foreign_key_columns FKC
inner join sys.objects SO_P on SO_P.object_id = FKC.parent_object_id
inner join sys.columns SC_P on (SC_P.object_id = FKC.parent_object_id) AND (SC_P.column_id = FKC.parent_column_id)
inner join sys.objects SO_R on SO_R.object_id = FKC.referenced_object_id
inner join sys.columns SC_R on (SC_R.object_id = FKC.referenced_object_id) AND (SC_R.column_id = FKC.referenced_column_id)
where
((SO_P.name = #tableName) AND (SO_P.type = 'U'))
OR
((SO_R.name = #tableName) AND (SO_R.type = 'U'))
In SQL server management studio, you can right click your table in the object explorer, and then select 'View Dependencies'. This will open a new window in which you can see all other objects (not just tables) that depend on your table, and on which your table depends.
Here is a stored procedure I put together based in part on the above answer.
-- =============================================
-- Author: R. Mycroft
-- Create date: 2012-08-08
-- Description: Lists foreign keys to & from a named table.
-- (Have yet to find this one via Google!)
-- =============================================
alter procedure usp_ListTableForeignKeys
#tableName varchar(300) = ''
as
begin
set nocount on;
select
object_name(parent_object_id) as childObjectName
, object_name(referenced_object_id) as parentObjectName
, name, type_desc, create_date
from sys.foreign_keys
where object_name(parent_object_id) = #tableName
or object_name(referenced_object_id) = #tableName
end
Using SSMS GUI:
In SQL server management studio (SSMS), you can right click your table and select 'View Dependencies'. This will open a new window in which you can see all the objects that depend on your table, and on which your table depends also.
Additionally If you want to do it with TSQL in where all objects that depends on your table
Approach-1: Using sp_depends store procedure , though sql server team is going to remove this feauture in future version but it still useful to get all the dependencies on the specified Object, includes Tables, Views, Stored Procedures, Constraints, etc., sql server team recommend to use sys.dm_sql_referencing_entities and sys.dm_sql_referenced_entities instead.
-- Query to find Table Dependencies in SQL Server:
EXEC sp_depends #objname = N'dbo.aspnet_users' ;
Approach-2:
-- Query to find Table Dependencies in SQL Server:
SELECT referencing_id,
referencing_schema_name,
referencing_entity_name
FROM sys.dm_sql_referencing_entities('dbo.aspnet_users', 'OBJECT');
Approach-3: Find Table dependencies in Function, Procedure and View
SELECT *
FROM sys.sql_expression_dependencies A, sys.objects B
WHERE referenced_id = OBJECT_ID(N'dbo.aspnet_users') AND
A.referencing_id = B.object_id
Approach-4:
-- Value 131527 shows objects that are dependent on the specified object
EXEC sp_MSdependencies N'dbo.aspnet_users', null, 1315327
If you want to get all objects on which your table depends on.
-- Value 1053183 shows objects that the specified object is dependent on
EXEC sp_MSdependencies N'dbo.aspnet_users', null, 1053183
If you've got these defined as foreign keys then just examine the table design and look at the Relationships dialog which will show you everything that's defined for the table.
Alternatively you can use "View Dependencies".
Try this
select
OBJECT_NAME(parent_object_id) as parent_object_name,
*
from sys.foreign_keys
where name = 'YourFKName'
Another option to get foreign keys.
-- CTE to fetch all primary key information.
WITH PrimaryKeys AS (
SELECT
s.name as [Schema],
t.name as [Table],
c.name as [Column],
ic.index_column_id AS [ColumnNumber]
FROM sys.index_columns ic
JOIN sys.columns c ON ic.object_id = c.object_id and ic.column_id = c.column_id
JOIN sys.indexes i ON ic.object_id = i.object_id and ic.index_id = i.index_id
JOIN sys.tables t ON i.object_id = t.object_id
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE i.is_primary_key = 1
),
-- CTE to fetch table information.
TableInfo AS (
SELECT
tab.name AS [Table],
col.name AS [Column],
sch.name AS [Schema],
tab.object_id AS TableId,
col.column_id AS ColumnId
FROM sys.tables tab
JOIN sys.schemas sch ON tab.schema_id = sch.schema_id
JOIN sys.columns col ON col.object_id = tab.object_id
)
-- Primary query selecting foreign keys and primary/dependent information.
SELECT
obj.name AS FK_NAME,
p.[Schema] AS [PrimarySchema],
p.[Table] AS [PrimaryTable],
p.[Column] AS [PrimaryColumn],
d.[Schema] AS [DependentSchema],
d.[Table] AS [DependentTable],
d.[Column] AS [DependentColumn],
prim.ColumnNumber AS IsDependentPrimaryColumn -- has value if is part of dependent table's primary key
FROM sys.foreign_key_columns fkc
JOIN sys.objects obj ON obj.object_id = fkc.constraint_object_id
JOIN TableInfo d ON d.TableId = fkc.parent_object_id AND d.ColumnId = fkc.parent_column_id
JOIN TableInfo p ON p.TableId = fkc.referenced_object_id AND p.ColumnId = fkc.referenced_column_id
-- Join in primary key information to determine if the dependent key is also
-- part of the dependent table's primary key.
LEFT JOIN PrimaryKeys prim ON prim.[Column] = d.[Column] AND prim.[Table] = d.[Table]
ORDER BY [PrimarySchema], [PrimaryTable], [DependentSchema], [DependentTable]
This will yield all foreign keys and their primary/dependent information. It also includes an extra column if the dependent column is part of the primary key in the dependent table - sometimes important to note that.
To get only the Users table, just add a WHERE clause before the final ORDER BY
WHERE PrimaryTable = 'Users'
Option to get all tables with Schema Names
select
SO_P.name as [parent table]
,SS_P.name as [parent table schema]
,SC_P.name as [parent column]
,'is a foreign key of' as [direction]
,SO_R.name as [referenced table]
,SS_R.name as [referenced table schema]
,SC_R.name as [referenced column]
,*
from sys.foreign_key_columns FKC
inner join sys.objects SO_P on SO_P.object_id = FKC.parent_object_id
inner join sys.schemas SS_P on SS_P.schema_id = SO_P.schema_id
inner join sys.columns SC_P on (SC_P.object_id = FKC.parent_object_id) AND (SC_P.column_id = FKC.parent_column_id)
inner join sys.objects SO_R on SO_R.object_id = FKC.referenced_object_id
inner join sys.schemas SS_R on SS_R.schema_id = SO_P.schema_id
inner join sys.columns SC_R on (SC_R.object_id = FKC.referenced_object_id) AND (SC_R.column_id = FKC.referenced_column_id)
where SO_P.type = 'U' OR SO_R.type = 'U'

How to identify whether the table has identity column

I want to find out whether the table has an identity column or not. Table is unknown to me. I have not done the structure of the table. Using Query?
I am using Sql Server Compact Edition.
IF (OBJECTPROPERTY(OBJECT_ID('TABLE_NAME'), 'TableHasIdentity') = 1)
ObjectProperty is available starting sql server 2008 Reference:
OBJECTPROPERTY
This query returns a table's identity column name:
CREATE PROCEDURE dbo.usp_GetIdentity
#schemaname nvarchar(128) = 'dbo'
,#tablename nvarchar(128)
AS
BEGIN
SELECT OBJECT_NAME(OBJECT_ID) AS TABLENAME,
NAME AS COLUMNNAME,
SEED_VALUE,
INCREMENT_VALUE,
LAST_VALUE,
IS_NOT_FOR_REPLICATION
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #tablename
AND OBJECT_SCHEMA_NAME(object_id) = #schemaname
END
Then form the code side.
Call this stored procedure using the datareader role, then check datareader.hasrows(). If the condition value is true (1), then the table has identity column if set. If not then it doesn't have an identity column.
I know it's long time ago but i found this helpful
try this :
IF EXISTS (SELECT * from syscolumns where id = Object_ID(#TABLE_NAME) and colstat & 1 = 1)
BEGIN
-- Do your things
END
Any of the below queries can be used to check if an Identity Column is present in the table
1)
SELECT *
FROM sys.identity_columns
WHERE OBJECT_NAME(object_id) = 'TableName'
2)
SELECT *
FROM sys.identity_columns
WHERE object_id = (
SELECT id
FROM sysobjects
WHERE name = 'TableName'
)
I would just like to add this option as well as I think it is the simplest
SELECT COLUMNPROPERTY(OBJECT_ID('TableName'),'ColumnName','isidentity')
One way to do this would be to make use of the stored procedure sp_help. I.e:
sp_help MyTable
This will return a DataSet that has all the information you would need on the table. There is a specific Table that has information on identities.
I.e:
If it does not contain an identity field, the Identity column will say: "No identity column defined".
#Pranay: he said Compact Edition. Stored procedures aren't supported, and there is no sys.anything.
This is the call:
SELECT Count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE AUTOINC_INCREMENT IS NOT NULL AND TABLE_NAME='this_table'
It will return either 1 (true) or 0 (false).
...
declare #tblhasIdentCol bit = IF (IDENT_CURRENT( #dbName +'.'+ #schemaName +'.'+ #tableName ) IS NOT NULL , 1 , 0 )
You get numeric value if table has identity
Very simple answer would be to run this:
SELECT IDENT_CURRENT('TABLE-NAME')
This would give max value of identity column if exists, if the column doesn't exist, it gives 1 as result.
Based on max value, you can identify which column is having that and determine the identity column.
This the query that get u all the tableNames, columnnames of the table, and is_identity or not in the selected database
SELECT
sys.columns.name
, sys.tables.name
, is_identity
FROM sys.columns
INNER JOIN sys.tables ON sys.tables.object_id = sys.columns.object_id
AND sys.columns.is_identity = 1
CREATE FUNCTION dbo.fnTableHasIdentity(#Tbl sysname)
RETURNS TINYINT
BEGIN
RETURN OBJECTPROPERTY(OBJECT_ID(#Tbl), 'TableHasIdentity')
END
--As simple as that!
select t.name as TableName,c.name as ColumnName
from sys.identity_columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = 'TableName'
If you like me, needed to be able to do this for tables in an arbitrary database, then I found the following solution:
IF EXISTS (
SELECT 1
FROM [database name].sys.identity_columns AS id_col
INNER JOIN [database name].sys.objects
ON objects.object_id = id_col.object_id
INNER JOIN [database name].sys.schemas
ON schemas.schema_id = objects.schema_id
AND schemas.name = 'schema name'
WHERE OBJECT_NAME(id_col.object_id, DB_ID('database name')) = 'table name'
) SELECT 1 ELSE SELECT 0
you can get the 1 or 0 Boolean Form if the current table has identity Columns by using this
SELECT Count(Column_ID) FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = 'tableName'
One way to list all Tables with their identity column if it exists
to get you desired table add at the end of the filter "and o.name='TableName'"
where Tbale Nam is the table you are looking for
SELECT o.[Name][TableName],i.[name][IdentityColName] FROM
sys.objects o
left outer join sys.identity_columns i on i.object_id=o.object_id
where o.type='U'