Dynamically determining table name given field name in SQL server - sql

Strange situation: I am trying to remove some hard coding from my code. There is a situation where I have a field, lets say "CityID", and using this information, I want to find out which table contains a primary key called CityID.
Logically, you'd say that it's probably a table called "City" but it's not... that table is called "Cities". There are some other inconsistencies in database naming hence I can never be sure if removing the string "ID" and finding out the plural will be sufficient.
Note: Once I figure out that CityID refers to a table called Cities, I will perform a join to replace CityID with city name on the fly. I will appreciate if someonw can also tell me how to find out the first varchar field in a table given its name.

SELECT name FROM sysobjects
WHERE id IN ( SELECT id FROM syscolumns WHERE name = 'THE_COLUMN_NAME' )
To get column information from the specified table:
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'myTable'

select table_name from information_schema.columns where column_name='CityID'

You can use the INFORMATION_SCHEMA tables to read metadata about the database.
SELECT
TABLE_NAME
FROM
[db].[INFORMATION_SCHEMA].[COLUMNS]
WHERE
COLUMN_NAME='CityID';
For a primer in what's in the INFORMAITON_SCHEMA, see INFORMATION_SCHEMA, a map to your database

The information you seek is all available in the information schema views. Note that you will find many sources telling you how to directly query the underlying system tables that these are views onto - and I must admit that I do the same when it's just to find something out quickly - but the recommended way for applications is to go through these views.
For example, to find your CityID column:
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'CityID'
To find the first varchar field in a table:
SELECT TOP 1 * FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME = 'TableName'
AND DATA_TYPE = 'varchar' -- This is off the top of my head!
ORDER BY ORDINAL_POSITION

As I understand from your question, you want to find tables which contain CITYID column in primary key
You can use SQL Server system views like sysindexes and sysindexkeys as shown in SQL tutorial to query database table primary keys including composite primary keys which are formed
SELECT
TBL.name as TableName
FROM sysobjects as PK
INNER JOIN sys.objects as TBL
on TBL.object_id = PK.parent_obj
INNER JOIN sysindexes as IND
on IND.name = PK.name AND
IND.id = TBL.object_id
INNER JOIN SysIndexKeys as KEYS
on KEYS.id = IND.id AND
KEYS.indid = IND.indid
INNER JOIN syscolumns as COL
on COL.id = KEYS.id AND
COL.colid = KEYS.colid
WHERE
PK.xtype = 'PK' AND
COL.name = 'CityID'

Related

TSQL see if column is part of unique index without using dynamic management function

I want to write a query to see information about whether a column in a table is part of a unique index or not.
Usually i write the following to get the information I need:
SELECT name
, is_part_of_unique_key
FROM sys.dm_exec_describe_first_result_set(N'SELECT * FROM dbo.Department', NULL, 1)
WHERE is_hidden = 0
the "is_part_of_unique_key" from the above query does the following according to MS:
Returns 1 if the column is part of a unique index (including unique
and primary constraints) and 0 if it is not. Returns NULL if it cannot
be determined that the column is part of a unique index. Is only
populated if browsing information is requested.
Link: https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-exec-describe-first-result-set-transact-sql?view=sql-server-2017
however I am in a situation where I dont have SELECT-permissions on the above mentioned table, so the query above will not work.
I need the information about whether the column is part of a unique index or not by looking at i.e. the INFORMATION_SCHEMA-views
I have permissions to do the following for instance, but this doesn't give me information about unique indexes:
SELECT
COLUMN_NAME AS name
,DATA_TYPE AS system_type_name
,CHARACTER_MAXIMUM_LENGTH
IS_NULLABLE
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME LIKE 'dbo.Department'
I am in doubt if sys.indexes will give me the correct results since i am interested in if the "column is
part of a unique index (including unique and primary constraints)"
So I am only interested in unique indexes. How would I write a query to see if the column is part of a unique index with the restriced permissions i have?
Help is much appreciated!
Let's assume you have this table:
CREATE TABLE MyIndexTestTable
(
MyIndexTestTableId INT NOT NULL IDENTITY(1,1),
code VARCHAR(10) NOT NULL UNIQUE,
otherUnique VARCHAR(10) NOT NULL,
name VARCHAR(100) NULL,
CONSTRAINT PK_MyIndexTestTable PRIMARY KEY(MyIndexTestTableId),
CONSTRAINT UQ2_MyIndexTestTable UNIQUE (otherUnique)
)
Then with the following statement you will get all columns with UNIQUE
constraint and which are part of the primary key:
SELECT COLUMN_NAME AS uniqueColumns FROM sys.objects c JOIN sys.objects t ON c.parent_object_id = t.object_id
JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu ON cu.TABLE_NAME = t.name AND cu.CONSTRAINT_NAME = c.name
WHERE c.type IN ('PK', 'UQ')
AND t.name = 'MyIndexTestTable'
This answer does not cover cases in which the primary key contains multiple columns - each of them are not unique. For this case you have to alter the query in order to exclude all primary key columns, if there is more than one. Please comment if you also need this example.
Something like sp_help has the Column index_description. You can pull it from that Logic
sp_helptext sp_help
Grab it from this Section in the Procedure -- DISPLAY TABLE INDEXES & CONSTRAINTS
This may Work for you.
Sp_help My Example Table
The following query will give you a list of unique indexes and columns involved with that index. Modify the where clause accordingly:
SELECT sys.indexes.name, sys.columns.name
FROM sys.tables
INNER JOIN sys.indexes ON sys.tables.object_id = sys.indexes.object_id
INNER JOIN sys.index_columns ON sys.indexes.object_id = sys.index_columns.object_id
AND sys.indexes.index_id = sys.index_columns.index_id
INNER JOIN sys.columns ON sys.index_columns.object_id = sys.columns.object_id
AND sys.index_columns.column_id = sys.columns.column_id
WHERE sys.tables.name = 'table name'
AND sys.indexes.is_unique = 1

SQL Query to lookup a column

I want to lookup if a column by the name of 'LOB' exist among thousands of views.
Schema name: PACONE
any help is appreciated here. Thanks.
That solution will depend on what Database Server you have.
If you have Oracle, go to Search an Oracle database for tables with specific column names?
If you have mySQL, go to How do i search a mysql database for a specific column name
If you have PostgreSQL, go to How to find a table having a specific column in postgresql
If you have SQL Server, this is a possible solution:
How-To: Find Fields or Tables Within a SQL Server Database
Suppose you need to find a field called GLASS_ID, you simply run this:
-- SEARCHING FOR A CERTAIN FIELD NAME --
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE UPPER(COLUMN_NAME) = 'GLASS_ID'
Similarly, you can look for all field names that end with 'CO'
-- SEARCHING FOR FIELD NAMES THAT END WITH... --
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, IS_NULLABLE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE UPPER(COLUMN_NAME) LIKE '%CO'
Of course, this is supposed to work under SQL Server, and that was tested in SQL Server 2005 only, but I guess that it will work in any recent version too.
use [your database name]
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE c.name = 'LOB'
ORDER BY schema_name, table_name;
First of all you should provide some information about your environment.
If you use Oracle you can query the dba_tab_columns with dab_view (user_ or all_ is also possible) e.g.:
select a.view_name
from dba_views a
join dba_tab_columns b
on a.view_name = b.table_name
where lower(b.column_name) = 'lob'
and lower(b.owner) = <view_owner>;

Searching for a table based on values contained in the table

I have a table with a reason_id foreign key. I need to map that back to its primary table. I have searched our databases for matching/similar column names but I wasn't able to find the table.
I have a list of values that would be associated with the reason_id. I'd like to search for tables that contain the list I have. Any help would be appreciated.
Here's the query I was running to search for columns:
select
t.name as Table_Name,
SCHEMA_NAME(schema_id) as schema_name,
c.name as Column_Name
from
sys.tables as t
inner join
sys.columns c
on
t.OBJECT_ID = c.OBJECT_ID
where
c.name like '%reason%'
There is no easy way to find the related data in other tables.
I'd try with tools such as ApexSQL Search or SQL Search. Both are free and you won’t go wrong with any of these.
If you want to do it with SQL only then identify all columns in all tables that have the same data type. To do so use sys.columns, sys.types and sys.tables views. Once you find all columns just try start writing queries for each table until you find the right one.
I’d go with something like this
select COUNT(*)
from tableX
where tableX.matchedColumn in
(
-- take 100 or more random rows from the original table
-- if result gives you a number that is near to the number of values listed here then you are most probably on the right track
)

Copy Column Into Existing Table using SQL

I want to create a column in databaseA with the same name, type, length and precision as another column in databaseB.
I need something like this:
INSERT INTO dbo.databaseA(col_name)
SELECT col_name
FROM dbo.databaseB;
GO
But the *col_name* does not yet exist in databaseA. I want to create it with the same type as *col_name* in databaseB.
I've also looked at:
ALTER TABLE table_name ADD col_name data_type
INSERT INTO dbo.databaseA(col_name)
SELECT col_name
FROM dbo.databaseB;
GO
But I don't know the data_type of the column I need to copy.
Edit:
** I'm using SQL Server 2008 R2 **
You can retrieve the datatype of the column from the database by querying the system views, similar to the following:
SELECT c.*, s.name
FROM sys.columns c
INNER JOIN sys.objects o
ON c.object_id = o.object_id
INNER JOIN sys.types s
ON c.user_type_id = s.user_type_id
WHERE o.name = 'B'
AND c.name = 'ColumnName'
You'll need to connect to DatabaseB, replace o.name = 'B' with your table's name and replace c.Name = 'ColumnName' with your column's name.
Once you have the datatype you would need to construct a DDL statement to add the column to the table in database A, something along the lines of the following:
ALTER TABLE dbo.MyTableName ADD MyColumnName DATA_TYPE_HERE
Once the table has been updated you can construct and execute your insert statement:
INSERT INTO DatabaseA.dbo.MyTableName (column list)
SELECT (column list)
FROM DatabaseB.dbo.MyTableName
Note that the above assumes both databases are located on the same SQL Server Instance and they both reside in the dbo schema.
If this is something you plan on using in the future you should add some defensive programming steps to make sure you only add the column if the column doesn't already exist in the table.

SQL Script To Generate a Database Dictionary **With Linked Fields**

I would like to generate a Data Dictionary for a SQL Server 2008 database that has one row for each field, and the following columns:
table_name
field_name
data_type
link_table (for when the field in question is a foreign key)
link_field (for when the field in question is a foreign key)
I can get the first 3 columns with something like the SQL script below...but I don't know how to get the last two columns of foreign key information. INFORMATION_SCHEMA.TABLE_CONSTRAINTS gets close, but doesn't have the data I'm looking for. Can someone help with this point?
SELECT TABLE_NAME,COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
Secondarily if anyone has any suggestions on additional fields which would be helpful please post.
The following query will duplicate a column if it is involved in more than one relationship.
Select C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.DATA_TYPE
, PKCol.TABLE_SCHEMA, PKCol.TABLE_NAME, PKCol.COLUMN_NAME
From INFORMATION_SCHEMA.COLUMNS As C
Left Join (INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As FKCol
Join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS As FK
On FK.CONSTRAINT_NAME = FKCol.CONSTRAINT_NAME
Join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE As PKCol
On PKCol.CONSTRAINT_NAME = FK.UNIQUE_CONSTRAINT_NAME)
On FKCol.TABLE_SCHEMA = C.TABLE_SCHEMA
And FKCol.TABLE_NAME = C.TABLE_NAME
ANd FKCol.COLUMN_NAME = C.COLUMN_NAME