Check If column exists or not in table and rename them - sql-server

I am trying to merge two different rules into one that should run in two databases server.
I did merged the files. but i am stuck at the this columns.
There are two columns with different names but the same data in the two databases. I want my query to check if if this column exist
First column - APE.RecProdOwner
Second Column - APE.ReconciliationOwner
I want my query to check for both these columns in the database and if one of the two exists then it should store the data into the new column name as “RecProdOwner”

You can use an EXISTS against the sys objects, and then simply use sys.sp_rename to rename the column:
USE Sandbox;
GO
CREATE TABLE dbo.YourTable ([APE.RecProdOwner] int,
ReconciliationOwner int);
GO
IF EXISTS (SELECT 1
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.name = N'dbo'
AND t.name = N'YourTable'
AND c.name = N'APE.RecProdOwner')
EXEC sys.sp_rename N'dbo.YourTable.[APE.RecProdOwner]','RecProdOwner','COLUMN';
IF EXISTS (SELECT 1
FROM sys.schemas s
JOIN sys.tables t ON s.schema_id = t.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
WHERE s.name = N'dbo'
AND t.name = N'YourTable'
AND c.name = N'APE.ReconciliationOwner')
EXEC sys.sp_rename N'dbo.YourTable.[APE.ReconciliationOwner]','ReconciliationOwner','COLUMN';
GO
SELECT *
FROM dbo.YourTable;
GO
DROP TABLE dbo.YourTable;

Related

Using column names from another table to define the name of a new table

I'm looking to create a new table name as the name of the column in a previous table but it can't seem to recognize the #table_name_2 variable. I'm trying to do the following;
DECLARE #table_name_2 varchar(MAX)
SET #table_name_2 =
(select
col.name as column_name
from sys.tables as tab
inner join sys.columns as col
on tab.object_id = col.object_id
left join sys.types as t
on col.user_type_id = t.user_type_id
where schema_name(tab.schema_id) = 'Staging' and tab.name = 'QACalculator' and col.column_id = 2)
CREATE TABLE #table_name_2
(
MI_KEY NOT NULL
ISSUE NULL
)

Need to change GUID to varchar or char

I am trying to use a reference table to update a code, but I am getting the error:
Conversion failed when converting from a character string to
uniqueidentifier
The ID is a guid: 086B9FE7-3980-47D7-BB05-003708F1D564 and the reference code I want to use is 4 characters, like H100.
I received the initial error when I tried to alter the datatype in the table and then update the file with the values from the reference table. I have tried converting and casting based on other articles, but even if I cast or convert successfully, I still get the same message.
RefTable:
Id | ReportCode
6340FCEA-161C-42F4-8D7F-46B4C2E6C4E2 | H100
DataTable:
CauseId
6340FCEA-161C-42F4-8D7F-46B4C2E6C4E2
Code I am using to try and update. The first works, and the second bring the error msg:
select cast(nvarchar(36), ID) as ID
from [dbo].[reftable]
UPDATE dbo.datatable
SET causeid = L.reportcode
FROM dbo.datatable S
join dbo.reftable L on S.causeid = L.id
Uniqueidentifier is a particular column type that holds 36 bytes, with some hyphen characters in the middle. Asigning a string value that doesn't match it's format will always fail when trying to convert it.
-- Conversion failed when converting from a character string to uniqueidentifier.
SELECT CONVERT(UNIQUEIDENTIFIER, 'H100')
-- OK
SELECT CONVERT(UNIQUEIDENTIFIER, 'c029f8be-29dc-41c1-8b38-737b4cc5a4df')
If you want to use a common VARCHAR as your new causeid value, you need to first convert the column type to VARCHAR (or NVARCHAR).
ALTER TABLE dbo.datatable ALTER COLUMN causeid VARCHAR(200) -- NOT NULL if you need
If you can't alter the data type it's probably because there is an INDEX or a CONSTRAINT linked to it. When you try to alter, the SQL engine will tell you which object is linked to it. You will have to drop them, alter the column type and then create them again.
I use these queries to check indexes and constraints. I updated the search values for your table.
DECLARE #table_name VARCHAR(200) = 'datatable'
DECLARE #column_name VARCHAR(200) = 'causeid'
-- Indexes
SELECT
SchemaName = SCHEMA_NAME(t.schema_id),
TableName = t.name,
IndexName = ind.name,
IndexType = CASE ind.index_id WHEN 0 THEN 'Heap' WHEN 1 THEN 'Clustered' ELSE 'Nonclustered' END,
Disabled = ind.is_disabled,
ColumnOrder = ic.index_column_id,
ColumnName = col.name,
ColumnType = y.name,
ColumnLength = y.max_length,
ColumnIncluded = ic.is_included_column
FROM
sys.indexes ind
INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN sys.tables t ON ind.object_id = t.object_id
INNER JOIN sys.types y ON y.user_type_id = col.user_type_id
WHERE
t.is_ms_shipped = 0 AND
t.name = #table_name AND
col.name = #column_name
ORDER BY
SchemaName,
t.name,
ind.name,
ic.index_column_id
-- Constraints
SELECT
TableName = t.Name,
ColumnName = c.Name,
dc.Name,
dc.definition
FROM
sys.tables t
INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id
INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id
WHERE
t.name = #table_name AND
c.name = #column_name
ORDER BY
t.Name

Get total size for a list of tables

I have a prod database that is very large in size. I need to copy this DB to make a test environment, however there is not enough disk space.
But actually there is no need to copy rows from tables containing user-data, only those tables that describe functionality are necessary. For tables with user-data I only need to copy table "description" (columns, indexes, triggers, ...).
How (with what query) can I estimate the size of DB without data from some tables?
SET NOCOUNT ON
DBCC UPDATEUSAGE(0)
-- DB size.
EXEC sp_spaceused
-- Table row counts and sizes.
CREATE TABLE #t
(
[name] NVARCHAR(128),
[rows] CHAR(11),
reserved VARCHAR(18),
data VARCHAR(18),
index_size VARCHAR(18),
unused VARCHAR(18)
)
INSERT #t EXEC sp_msForEachTable 'EXEC sp_spaceused ''?'''
SELECT *
FROM #t
-- # of rows.
SELECT SUM(CAST([rows] AS int)) AS [rows]
FROM #t
DROP TABLE #t
*by Alexander Groß *
Link to source
SELECT
schema_qualified_table = s.name + '.' + t.name,
KB = SUM(ps.reserved_page_count) * 8192/1024.0
FROM sys.tables AS t
INNER JOIN sys.schemas AS s ON t.[schema_id] = s.[schema_id]
INNER JOIN sys.dm_db_partition_stats AS ps
ON t.[object_id] = ps.[object_id]
WHERE s.name + '.' + t.name IN (N'dbo.table1', N'dbo.table2', ...)
-- list of tables you do care about ^^^^^^^^^^ ^^^^^^^^^^
GROUP BY s.name + '.' + t.name;
A little tidier might be:
;WITH x AS
(
SELECT o = t.[object_id], n = s.name + '.' + t.name
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
)
SELECT
schema_qualified_table = x.n,
KB = SUM(ps.reserved_page_count) * 8192/1024.0
FROM x INNER JOIN sys.dm_db_partition_stats AS ps
ON x.o = ps.[object_id]
WHERE x.n IN (N'dbo.table1', N'dbo.table2', ...);
Posting my expansion to Aaron Bertrand's answer, just for readability. Only difference is adding the join to the SCHEMAS table, and including schema name in the output and group by.
SELECT
s.name,
t.name,
KB = SUM(ps.reserved_page_count) * 8192/1024.0
FROM sys.tables AS t
INNER JOIN sys.dm_db_partition_stats AS ps
ON t.[object_id] = ps.[object_id]
INNER JOIN sys.schemas S
ON t.schema_id = s.schema_id
WHERE t.name IN (<YOUR TABLES GO HERE) -- list of tables you do care about
GROUP BY t.name,
s.name;
As Aaron has rightly pointed out, trying to filter on a combination of tables and schemas could get ugly very fast. You could easily end up with a huge collection of ORs:
(S.SCHEMA = 'SCHEMA1' and T.NAME = 'FOO')
OR
(S.SCHEMA = 'SCHEMA2' and T.NAME = 'FOO')
OR
(S.SCHEMA = 'SCHEMA1' and T.name = 'BAR')
...

Query to Recursively Identify Object Dependencies

I have a complex query with several tables, views and functions within it. The functions and views split off into more views and functions that potentially split off into more views and functions within them.
This query is having performance issues so I want to get a clear and concise list of all the objects that are being referenced within my query so I have a basis for my investigation. How do I get this list of objects?
DESCRIPTION
Wrote this Stored Procedure below which RECURSIVELY lists all the dependent child objects and child's dependent objects and child's child...etc. The input parameter can be Stored Proc, User Function, View.
Can easily be altered to get a Unique List of Column 5, regardless of what Level the Object was called and how deep and by which object.
COLUMNS
UsedByObjectId - The parent object that uses the dependent object
UsedByObjectName - The name of the parent object
UsedByObjectType - Type of the parent object (P,V,FN)
DependentObjectId - The child object the parent uses
DependentObjectName - Name of the child object
DependentObjectType - Type of the dependent child object (P,V,FN, U)
Level - How deep, the nested recursive level which the object is used
THE CODE
--=========================================================================
--=========================================================================
--== utlGetAllDependentObjectsRecursive - Uses recursive common table
--== expression to recursively get all the dependent objects as well
--== as the child objects and child's child objects of a
--== Stored Procedure or View or Function. can be easily modified to
--== include all other types of Objects
--=========================================================================
--=========================================================================
CREATE PROCEDURE utlGetAllDependentObjectsRecursive
(
-- Supports Stored Proc, View, User Function, User Table
#PARAM_OBJECT_NAME VARCHAR(500)
)
AS
BEGIN
WITH CTE_DependentObjects AS
(
SELECT DISTINCT
b.object_id AS UsedByObjectId,
b.name AS UsedByObjectName, b.type AS UsedByObjectType,
c.object_id AS DependentObjectId,
c.name AS DependentObjectName , c.type AS DependenObjectType
FROM sys.sysdepends a
INNER JOIN sys.objects b ON a.id = b.object_id
INNER JOIN sys.objects c ON a.depid = c.object_id
WHERE b.type IN ('P','V', 'FN') AND c.type IN ('U', 'P', 'V', 'FN')
),
CTE_DependentObjects2 AS
(
SELECT
UsedByObjectId, UsedByObjectName, UsedByObjectType,
DependentObjectId, DependentObjectName, DependenObjectType,
1 AS Level
FROM CTE_DependentObjects a
WHERE a.UsedByObjectName = #PARAM_OBJECT_NAME
UNION ALL
SELECT
a.UsedByObjectId, a.UsedByObjectName, a.UsedByObjectType,
a.DependentObjectId, a.DependentObjectName, a.DependenObjectType,
(b.Level + 1) AS Level
FROM CTE_DependentObjects a
INNER JOIN CTE_DependentObjects2 b
ON a.UsedByObjectName = b.DependentObjectName
)
SELECT DISTINCT * FROM CTE_DependentObjects2
ORDER BY Level, DependentObjectName
END
I saw this post to identify all the objects that reference a particular synonym and used the base logic in the answer in a recursive CTE to identify all the objects related to a comma-delimited list of the objects within the top level query being executed.
Declare #baseObjects Nvarchar(1000) = '[Schema].[Table],[Schema].[View],[Schema].[Function],[Schema].[StoredProc]',
#SQL Nvarchar(Max);
Declare #objects Table (SchemaName Varchar(512), TableName Varchar(512), ID Int, xtype Varchar(10));
Set #SQL = 'Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sysobjects so
Join sys.schemas ss
On so.uid = ss.schema_id
Where so.id In (Object_ID(''' + Replace(#baseObjects,',','''),Object_ID(''') + '''))';
Insert #objects
Exec sp_executeSQL #SQL;
With test As
(
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From sys.sql_expression_dependencies sed
Join #objects vo
On sed.referencing_id = vo.ID
Join sysobjects so
On sed.referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
Union All
Select ss.name As SchemaName,
so.name As TableName,
so.id,
so.xtype
From test
Join sys.sql_expression_dependencies sed
On sed.referencing_id = test.id
And sed.referencing_id <> sed.referenced_id
Join sysobjects so
On sed. referenced_id = so.id
Join sys.schemas ss
On so.uid = ss.schema_id
)
Select Distinct *
From test
Union
Select *
From #objects;
Check This one, You will get all recursive objects.
WITH Refobjects
(referencing_object_name,referencing_object_type_desc)
AS
(
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
WHERE
sed.referenced_entity_name = 'Your Object Name'
UNION ALL
SELECT
o.name AS referencing_object_name,
o.type_desc AS referencing_object_type_desc
FROM
sys.sql_expression_dependencies sed
INNER JOIN
sys.objects o ON sed.referencing_id = o.[object_id]
INNER JOIN Refobjects ON sed.referenced_entity_name = Refobjects.referencing_object_name
)
SELECT distinct * FROM Refobjects
Order by 2 desc,1 ;
In SQL Server 2008 there are two new Dynamic Management Functions introduced to keep track of object dependencies: sys.dm_sql_referenced_entities and sys.dm_sql_referencing_entities:
1/ Returning the entities that refer to a given entity:
SELECT
referencing_schema_name, referencing_entity_name,
referencing_class_desc, is_caller_dependent
FROM sys.dm_sql_referencing_entities ('<TableName>', 'OBJECT')
2/ Returning entities that are referenced by an object:
SELECT
referenced_schema_name, referenced_entity_name, referenced_minor_name,
referenced_class_desc, is_caller_dependent, is_ambiguous
FROM sys.dm_sql_referenced_entities ('<StoredProcedureName>', 'OBJECT');
Another option is to use a pretty useful tool called SQL Dependency Tracker from Red Gate.
Based on #Raju Chavan's answer above, which works great. However...
I've added support for schemas, as well as returning (and ordering by) the recursion level, so one can easily turn it into a script to refresh referencing objects in the correct order, using sp_refreshsqlmodule (see point 3 below).
WITH
cRefobjects AS (
SELECT o.name, s.name AS sch, o.type_desc, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<your schema>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<your object name>'
UNION ALL
SELECT o.name, s.name AS sch, o.type_desc, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT DISTINCT name, sch, type_desc, level
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
A few things to consider:
Replace <your schema> and <your object> with with what you require.
When the referenced object does not have a schema prefix in the referencing object, the schema is actually unknown, hence the predicate above OR sed.referenced_schema_name IS NULL. This may get the wrong referencing object if you're not following best practices in your database objects.
My goal in seeking and finding this answer was to write a script to refresh referenced objects in the database automatically after editing a view, using sp_refreshsqlmodule. To do this, just wrap the CTE shown above as follows. This prints the required SQL for refreshing the referencing objects in the correct order:
DECLARE #SQL NVARCHAR(4000); SET #SQL = '';
WITH
cRefobjects AS (
...
)
--SELECT DISTINCT name, sch, type_desc, level
SELECT #SQL = #SQL + 'EXEC sys.sp_refreshsqlmodule ''' + sch + '.' + name + '''' + CHAR(13)+CHAR(10)
FROM cRefobjects
ORDER BY level, type_desc DESC, name;
PRINT #SQL
I have improved above answers as none was working for me.
I needed a way to refresh complex nested objects by type sp_refreshsqlmodule.
You need to update and <TYPE_NAME> to your own.
Following method work for me:
WITH cRefobjects AS (
SELECT o.name, s.name AS sch, o.type, 1 AS level
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
WHERE (sed.referenced_schema_name = '<SCHEMA>' OR sed.referenced_schema_name IS NULL)
AND sed.referenced_entity_name = '<TYPE_NAME>'
UNION ALL
SELECT o.name, s.name AS sch, o.type, cRefobjects.level + 1 AS level
FROM
sys.sql_expression_dependencies AS sed
INNER JOIN sys.objects o ON o.object_id = sed.referencing_id
INNER JOIN sys.schemas AS s ON s.schema_id = o.schema_id
INNER JOIN cRefobjects ON sed.referenced_entity_name = cRefobjects.name
AND sed.referenced_schema_name = cRefobjects.sch
)
SELECT name, MAX(level) as level, 'EXEC sys.sp_refreshsqlmodule #name = ''' + sch + '.' + name + '''', type
FROM cRefobjects
GROUP BY name, sch, type
ORDER BY level, type, name;

TSQL: How to check if column is fulltext enabled?

I need to modify a column definition, but I would like to check if the column is full text enabled first. Is there a way to do such a check in a TSQL script?
I'm using SQL Server 2005.
You could try using the COLUMNPROPERTY() function.
DECLARE #value INT;
SELECT #value = COLUMNPROPERTY(OBJECT_ID('schema.table'), 'column_name', 'IsFulltextIndexed')
IF (#value = 1)
PRINT 'Fulltext column'
ELSE
PRINT 'No Fulltext column'
You can try something like this:
SELECT *
FROM sys.columns c
INNER JOIN sys.fulltext_index_columns fic ON c.object_id = fic.object_id
AND c.column_id = fic.column_id
If you need to limit it to a given table, use this:
SELECT *
FROM sys.columns c
INNER JOIN sys.fulltext_index_columns fic ON c.object_id = fic.object_id
AND c.column_id = fic.column_id
WHERE c.object_id = OBJECT_ID('YourTableNameHere')

Resources