SQL View Columns - sql-server

This is probably a strange question... Hopefully, someone enjoys the more esoteric portion of SQL. :)
I have some views with many columns. The column widths are obstructive to reviewing the data. Once a column width is manually adjust and the view is saved, the column is perpetually saved at that width unless manually changed and again saved.
This makes me wonder how SQL saves column widths. Is there a table containing that data? If so, could an updated query revise all the columns for a given table to a defined width? If so, how?
Just FYI, my DBA and I spent a good while trying to figure this out. I am not asking without first endeavoring to solve it myself. I am a novice with SQL and hope for more experienced guidance.

They are stored in the extended properties. You can review them either in the properties window for the view in question or by scripting them out. If scripting out you need to ensure that you have selected the option to script extended properties hidden behind the advanced button. You can also set the default options in the options of SSMS.
Note that if you have not used the view designer there will be no extended properties.

Solution: use sp_refreshview (this demo shows that SQL Server doesn't automatically update metadata information for dbo.MyView after I change the maximum length for dbo.MyTable.Col2 and we have to use sp_refreshview [or ALTER VIEW, DROP & CREATE] to update metadata for the view):
IF EXISTS(SELECT * FROM sys.views t WHERE t.object_id = OBJECT_ID(N'dbo.MyView'))
BEGIN
DROP VIEW dbo.MyView;
END
IF EXISTS(SELECT * FROM sys.tables t WHERE t.object_id = OBJECT_ID(N'dbo.MyTable'))
BEGIN
DROP TABLE dbo.MyTable;
END
CREATE TABLE dbo.MyTable
(
Col1 INT IDENTITY(1,1) PRIMARY KEY,
Col2 VARCHAR(3) NULL
);
GO
CREATE VIEW dbo.MyView
AS
SELECT * FROM dbo.MyTable;
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 3
*/
ALTER TABLE dbo.MyTable
ALTER COLUMN Col2 VARCHAR(10);
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 3
*/
EXEC sp_refreshview 'dbo.MyView';
GO
SELECT cols.COLUMN_NAME, cols.DATA_TYPE, cols.CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_SCHEMA = 'dbo'
AND cols.TABLE_NAME = 'MyView'
AND cols.COLUMN_NAME = 'Col2'
GO
/*
COLUMN_NAME DATA_TYPE CHARACTER_MAXIMUM_LENGTH
----------- --------- ------------------------
Col2 varchar 10
*/

Related

T-SQL Check if the database contains certain tables and columns MSSQL

My goal is to continue in the procedure only with the database selected if it contains a specific table and a specific column.
So that I don't get an error message later when selecting that this column doesn't exist.
Background:
It is the case that database A table A has a more current status than database B with table A. In database B of table A a column is missing, which is the reason for the error that this column does not exist. Which I also do not want to add.
This is my attempt so far:
exec sp_MSforeachdb
'
use [?]
IF (''?'' NOT LIKE ''%example%'' AND ''?'' NOT LIKE ''%example_two%''
AND EXISTS(Select 1 from sys.tables where name = ''Table1'')
AND EXISTS(Select 1 from sys.tables where name = ''Table2'')
AND ''?'' NOT IN (SELECT * FROM Database.dbo.Blacklist)
)
BEGIN
IF(EXISTS(SELECT myColumn FROM Table1 Where ID = 5 AND XYZ = 3)) BEGIN.....'
Even when i switch instead of
..
AND EXISTS(Select 1 from sys.tables where name = ''Table1'')
AND EXISTS(Select 1 from sys.tables where name = ''Table2'')
..
To:
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''Table1''
AND COLUMN_NAME = ''MyExample''
it will not work the error log outputs: Incorrect syntax near 'TableXX'.
The error log gives me all databases that are practically checked, system databases as well.
Alternative it would also be helpful if someone knows how to use a case when in the select by trying to store an alternative value once the column does not exist e.g. like this:
'SELECT...
CASE WHEN exists(
SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME =''TableX'' AND COLUMN_NAME = ''ColumnX'')
THEN ''ST.ColumnX''
ELSE ''0 AS ColumnX''
END
FROM ...'
I just want to select databases that have the valid table and column, whenever I don't exist I take another table, this works until I find a table where a column doesn't exist, the column is however my select statement therefore I get an error, I want to focus on the alternative question, is there a way to check if the column exists in the current table? before assigning a value?
Case WHEN ColumnX exists THEN (ValueOfColumnX) ELSE 0 END AS Column.
Thank you in advance for any help
Use one single quotes when you are specifying the names of your tables and columns
SELECT 1 FROM your_databasename.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table1'
AND COLUMN_NAME = 'MyExample'
If you want to check if a column exists in a table try looking into this thread

Join a table whose name is stored in the first table

I have a first table [TABLE1] with columns [ID], [Description], [DetailTable]. I want to join [TABLE1] with the [DetailTable]. The name of [DetailTable] is stored in [TABLE1] column.
"SELECT * FROM TABLE1 CROSS JOIN ?????"
Any suggestions?
So... if you cheat and SELECT * from the detailtab, you could do something a bit like this, with dynamic SQL:
-- For the example, choose either 1 or 2 to see the #foo table or the #bar table
DECLARE #Id INT = 1
-- EXAMPLE SCENARIO SETUP --
CREATE TABLE #ListOfTables
( ID INT IDENTITY(1,1) NOT NULL
,[Description] NVARCHAR(255) NOT NULL
,[DetailTable] NVARCHAR(255) NOT NULL);
CREATE TABLE #foo
(Foothing VARCHAR(20));
CREATE TABLE #bar
(Barthing VARCHAR(20));
-- TEST VALUES --
INSERT #ListOfTables VALUES ('foo','#foo'),('bar','#bar');
INSERT #foo VALUES ('A foothing Foothing');
INSERT #bar VALUES ('A barthing Barthing');
-- THE SCRIPT --
DECLARE #SQL NVARCHAR(MAX) = '';
SELECT #SQL =
' SELECT Tab.Id, Tab.[Description], Tab2.*
FROM #ListOfTables AS Tab
CROSS JOIN ' + T.DetailTable + ' AS Tab2
WHERE Tab.Id = ' + CONVERT(VARCHAR(10),#Id)
FROM #ListOfTables T
WHERE T.Id = #Id;
PRINT #SQL
EXEC sp_executesql #SQL;
-- CLEAN UP --
DROP TABLE #ListOfTables;
DROP TABLE #bar;
DROP TABLE #foo;
However, I have to agree with the comments that this is a pretty nasty way to do things. If you want to choose particular columns and the columns are different for each detail table, then things will start to get really unpleasant... Does this give you something you can start with?
Remember, the best solution will almost certainly involve redesigning things so you don't have to jump through these hoops!
All of the detail tables must have identical schema.
Create a view that unions all the tables
CREATE VIEW vAllDetails AS
SELECT 'DETAIL1' table_name, * from DETAIL1
UNION ALL
SELECT 'DETAIL2' table_name, * from DETAIL2
UNION ALL
SELECT 'DETAIL3' table_name, * from DETAIL3
When you join against this view, SQL Server can generate a plan that uses a "startup predicate expression". For example, a plan like this: sample plan. At first glance, it looks like SQL is going to scan all of the detail tables, but it won't. The left most filters include a "startup predicate", so for each row we read from table1, only if TableName matches will that branch be executed.

How to get the datatype of a column of a view in SQL Server?

I want to get the datatype of a column of a view in SQL Server. Is there an efficient way to do that?
I have to get the Database Name, Schema, View Name all dynamically from one database, look for the view in another database and find the data type of the column in the third database.
E.g.
SELECT #db2 = Name FROM db1.schema.databases
SELECT #c = Name FROM db1.schema.columns
SELECT #v = Name FROM db1.schema.views
SELECT #datatype = query to get {datatype} of column {c} from {db2}.{schema}.{v}
Here column {c} of {db2}.{schema}.{v} can refer another database say {db3}
Please suggest.
Don't know exactly what you need, but this might help you:
USE master;
GO
CREATE VIEW dbo.TestView AS
SELECT * FROM master..spt_values;
GO
--This is the view's output
SELECT * FROM dbo.TestView;
GO
--Set your variables
DECLARE #db2 VARCHAR(100) = 'master';
DECLARE #c VARCHAR(100) = 'type';
DECLARE #vSchema VARCHAR(100) = 'dbo';
DECLARE #vName VARCHAR(100) = 'TestView'
--The query will display the DATA_TYPE and all other columns returned by INFORMATION_SCHEMA.COLUMNS
SELECT c.DATA_TYPE
,c.*
FROM master.INFORMATION_SCHEMA.COLUMNS AS c
WHERE c.TABLE_NAME=#vName
AND c.TABLE_SCHEMA=#vSchema
AND c.COLUMN_NAME=#c
AND c.TABLE_CATALOG=#db2; --forgot this in the first post...
--Clean-Up
GO
DROP VIEW dbo.TestView;
It's a bit fuzzy, that the COLUMNS view returns tables and views as if they were the same. The advantage: You can use the same approach to check a table's column...
Hint: This INFORMATION_SCHEMA.COLUMNS is just a built-in view looking into the corresponding sys tables.

Deleting specific rows from all tables

I have a database with a lot of tables.
In each table there is a column named "LicenseID" (bigint). How can I delete all rows, from all tables, that contain the value "2" in the column "LicenseID" ?
Best regards!
You didn't mentioned which database are you working with.
I assume it is SQL Server
First check your result with following query
SELECT * FROM table WHERE LicenseID LIKE '%2%'
or
SELECT * FROM table WHERE Contains(LicenseID, 2) > 0
Then Delete all those rows with above condition.
DELETE FROM table WHERE LicenseID LIKE '%2%'
or
DELETE FROM table WHERE Contains(LicenseID, 2) > 0
I have not tested it and don't know what type of database are you using. Answer can be little different in different databases.
You can use INFORMATION_SCHEMA.COLUMNS to generate the delete statements dynamically.
Something like this should do the trick:
DECLARE #Sql varchar(max) = ''
SELECT #Sql = #Sql + 'DELETE FROM '+ TABLE_NAME +' WHERE LicenseID = 2; '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'LicenseID'
EXEC(#Sql)
The reason I've used INFORMATION_SCHEMA.COLUMNS and not INFORMATION_SCHEMA.TABLES is to prevent an error in case there is a table that doesn't contain the LicenseID column.

Add a column to a table, if it does not already exist

I want to write a query for MS SQL Server that adds a column into a table. But I don't want any error display, when I run/execute the following query.
I am using this sort of query to add a table ...
IF EXISTS (
SELECT *
FROM sys.objects
WHERE OBJECT_ID = OBJECT_ID(N'[dbo].[Person]')
AND TYPE IN (N'U')
)
But I don't know how to write this query for a column.
You can use a similar construct by using the sys.columns table io sys.objects.
IF NOT EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(N'[dbo].[Person]')
AND name = 'ColumnName'
)
IF COL_LENGTH('table_name', 'column_name') IS NULL
BEGIN
ALTER TABLE table_name
ADD [column_name] INT
END
Another alternative. I prefer this approach because it is less writing but the two accomplish the same thing.
IF COLUMNPROPERTY(OBJECT_ID('dbo.Person'), 'ColumnName', 'ColumnId') IS NULL
BEGIN
ALTER TABLE Person
ADD ColumnName VARCHAR(MAX) NOT NULL
END
I also noticed yours is looking for where table does exist that is obviously just this
if COLUMNPROPERTY( OBJECT_ID('dbo.Person'),'ColumnName','ColumnId') is not null
Here's another variation that worked for me.
IF NOT EXISTS (SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE upper(TABLE_NAME) = 'TABLENAME'
AND upper(COLUMN_NAME) = 'COLUMNNAME')
BEGIN
ALTER TABLE [dbo].[Person] ADD Column
END
GO
EDIT:
Note that INFORMATION_SCHEMA views may not always be updated, use SYS.COLUMNS instead:
IF NOT EXISTS (SELECT 1
FROM SYS.COLUMNS....
IF NOT EXISTS (SELECT * FROM syscolumns
WHERE ID=OBJECT_ID('[db].[Employee]') AND NAME='EmpName')
ALTER TABLE [db].[Employee]
ADD [EmpName] VARCHAR(10)
GO
I Hope this would help. More info
When checking for a column in another database, you can simply include the database name:
IF NOT EXISTS (
SELECT *
FROM DatabaseName.sys.columns
WHERE object_id = OBJECT_ID(N'[DatabaseName].[dbo].[TableName]')
AND name = 'ColumnName'
)
IF NOT EXISTS (SELECT 1 FROM SYS.COLUMNS WHERE
OBJECT_ID = OBJECT_ID(N'[dbo].[Person]') AND name = 'DateOfBirth')
BEGIN
ALTER TABLE [dbo].[Person] ADD DateOfBirth DATETIME
END

Resources