SQL Search for a Binary value - sql

I've seen similar queries where a string or character value is used to search an entire database. Those queries do not return results that lie in a BINARY(8) field. I've tried to modify those queries to no avail.
Is there a way to search the entire database for specific binary values, such as 0x0000000000000017?
Thanks guys.

You can use the system tables to find this.
MSSQL:
SELECT t.name AS table_name,
c.name AS column_name,
ty.name
FROM sys.tables AS t
INNER JOIN sys.columns c
ON t.OBJECT_ID = c.OBJECT_ID
INNER JOIN sys.types ty
ON t.schema_id = ty.schema_id
WHERE ty.system_type_id = 173
ORACLE:
SELECT owner,table_name, column_name,data_TYPE
FROM all_tab_columns where data_TYPE = 'RAW';

Well...
select *
from foo
where foo.binary8column = 0x0000000000000017
should do. If you want to enumerate all the tables and find all the binary or varbinary columns, this query
select table_name = object_schema_name(tn.object_id) + '.' + tn.name ,
column_name = c.name ,
type = t.name + '(' + convert(varchar,c.max_length) + ')'
from sys.types t
join sys.columns c on c.system_type_id = t.system_type_id
join sys.tables tn on tn.object_id = c.object_id
where t.name in ( 'binary', 'varbinary' )
and c.max_length >= 8
should give enough information to generate the queries for every such table.

Related

Compare columns data types and size in same database in SQL Server

I need a query that could help me to compare column datatype and column size between two tables in same database.
For example I have these sample tables in the same database:
Table Names
-----------
I_A
I_B
I_C
T_A
T_B
T_C
ABC
I have to compare columns data types or columns size is mismatched between I AND T tables.
For example, I have to compare I_A with T_A table and I_B with T_B table like this.
I believe a query like this will identify column differences. If you also need to identify columns that exist on one table but not the other, use a FULL OUTER JOIN in the final SELECT tweak the WHERE clause to include rows with a NULL in either I or T values.
WITH
i_tables AS (
SELECT
RIGHT(t.name, 1) AS table_suffix
, c.name AS column_name
, ty.name AS type_name
, c.max_length
, c.precision
, c.scale
, c.is_nullable
FROM sys.tables AS t
JOIN sys.columns AS c ON
c.object_id = t.object_id
JOIN sys.types AS ty ON
ty.system_type_id = c.system_type_id
AND ty.user_type_id = c.user_type_id
WHERE t.name LIKE 'I[_]_'
)
,t_tables AS (
SELECT
RIGHT(t.name, 1) AS table_suffix
, c.name AS column_name
, ty.name AS type_name
, c.max_length
, c.precision
, c.scale
, c.is_nullable
FROM sys.tables AS t
JOIN sys.columns AS c ON
c.object_id = t.object_id
JOIN sys.types AS ty ON
ty.system_type_id = c.system_type_id
AND ty.user_type_id = c.user_type_id
WHERE t.name LIKE 'T[_]_'
)
SELECT *
FROM i_tables
JOIN t_tables ON
t_tables.table_suffix = i_tables.table_suffix
AND t_tables.column_name = i_tables.column_name
WHERE
t_tables.type_name <> i_tables.type_name
AND t_tables.max_length <> i_tables.max_length
AND t_tables.precision <> i_tables.precision
AND t_tables.scale <> i_tables.scale
AND t_tables.is_nullable <> i_tables.is_nullable;

How to find which indexes and constraints contain a specific column?

I am planing a database change and I have a list of columns included in process. Can I list all indexes in which is a specific column included?
Edit
So far I have (combined from answers):
declare #TableName nvarchar(128), #FieldName nvarchar(128)
select #TableName= N'<<Table Name>>', #FieldName =N'<<Field Name>>'
(SELECT distinct systab.name AS TABLE_NAME,sysind.name AS INDEX_NAME, 'index'
FROM sys.indexes sysind
INNER JOIN sys.index_columns sysind_col
ON sysind.object_id = sysind_col.object_id and sysind.index_id = sysind_col.index_id
INNER JOIN sys.columns sys_col
ON sysind_col.object_id = sys_col.object_id and sysind_col.column_id = sys_col.column_id
INNER JOIN sys.tables systab
ON sysind.object_id = systab.object_id
WHERE systab.is_ms_shipped = 0 and sysind.is_primary_key=0 and sys_col.name =#FieldName and systab.name=#TableName
union
select t.name TABLE_NAME,o.name, 'Default' OBJ_TYPE
from sys.objects o
inner join sys.columns c on o.object_id = c.default_object_id
inner join sys.objects t on c.object_id = t.object_id
where o.type in ('D') and c.name =#FieldName and t.name=#TableName
union
SELECT u.TABLE_NAME,u.CONSTRAINT_NAME, 'Constraint' OBJ_TYPE
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE u
where u.COLUMN_NAME = #FieldName and u.TABLE_NAME = #TableName
) order by 1
But I am not too happy with combining of sys. and 'INFORMATION_SCHEMA.' Can it be avoided?
---Using sp_helpindex and your TableName
exec sp_helpindex YourTableName
---Using sys.tables with your TableName and ColumnName
select distinct c.name, i.name, i.type_desc,...
from sys.indexes i
join sys.index_columns ic on i.index_id = ic.index_id
join sys.columns c on ic.column_id = c.column_id
where i.object_id = OBJECT_ID(N'YourTableName') and c.name = 'YourColumnName'
EDIT: As per comment, you can also join object_Ids without using distinct
select c.name, i.name, i.type_desc
from sys.indexes i
join sys.index_columns ic on i.index_id = ic.index_id and i.object_id = ic.object_id
join sys.columns c on ic.column_id = c.column_id and ic.object_id = c.object_id
where i.object_id = OBJECT_ID(N'YourTableName') and c.name = 'YourColumnName'
SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
USE TABLE_NAME IN WHERE if you what to know the constraint on a table.
and use column_name if you know the column name.
To get information regarding all indexes in which is a specific column is included following two catalog views can be used:
sys.indexes , sys.index_columns
Query:
SELECT
sysind.name AS INDEX_NAME
,sysind.index_id AS INDEX_ID
,sys_col.name AS COLUMN_NAME
,systab.name AS TABLE_NAME
FROM sys.indexes sysind
INNER JOIN sys.index_columns sysind_col
ON sysind.object_id = sysind_col.object_id and sysind.index_id = sysind_col.index_id
INNER JOIN sys.columns sys_col
ON sysind_col.object_id = sys_col.object_id and sysind_col.column_id = sys_col.column_id
INNER JOIN sys.tables systab
ON sysind.object_id = systab.object_id
WHERE (1=1)
AND systab.is_ms_shipped = 0
AND sys_col.name IN(specific column list for which indexes are to be queried)
ORDER BY
systab.name,sys_col.name, sysind.name,sysind.index_id
Hope this helps!
If you have access to the sys schema on your database then you can query sys.indexes to get the index ID and use that with the function index_col to get the columns. The final parameter for index_col is the index of the column within the index (i.e. if there are 3 columns in the index you would have to call index_col 3 times with 1, 2, 3 in the last parameter)
select index_id from sys.indexes
where object_id = object_id(#objectname)
select index_col(#objectname, #indexid, 1)
This should give you constraints as well as they are just special indexes.

Finding SQL Base Type for a User-Defined Type

I am working with a legacy database that has a large number of user-defined SQL types. I am writing a method in .NET in which I am defining parameters in the SqlParameter object. I need the underlying SQL types for the user defined types in order to properly define the parameters as I create them dynamically at runtime.
To do this I created this procedure:
(#typename sysname)
AS
SET NOCOUNT ON
SELECT distinct
st.name as UserType,
t.precision, t.max_length,
bt.name as BaseType
FROM
dbo.syscolumns c
INNER JOIN dbo.systypes st ON st.xusertype = c.xusertype
INNER JOIN dbo.systypes bt ON bt.xusertype = c.xtype
inner join sys.types t on st.name = t.name
WHERE
st.name = 'bVendor'
I am wondering if this is the best way to go about getting the underlying base type for a user defined type?
You shouldn't be using systypes or syscolumns - these are backward compatibility views, and sys.types and sys.columns are highly preferred unless you are trying to write code that works on SQL Server 2000+ (which I don't recommend either).
To get the information about a type you already know the name of:
SELECT name, precision, scale, max_length
FROM sys.types AS t
WHERE name = 'bVendor';
To get the information for all the user-defined types in a database:
SELECT name, precision, scale, max_length
FROM sys.types AS t
WHERE is_user_defined = 1;
To get the information about all the types (system and user-defined) for a specific table:
UPDATE to include the base type:
SELECT
[column] = c.name,
[base type] = COALESCE(bt.name, t.name),
[defined type] = t.name,
t.precision,
t.scale,
t.max_length
FROM sys.columns AS c
INNER JOIN sys.types AS t
ON c.system_type_id = t.system_type_id
AND c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.types AS bt
ON t.is_user_defined = 1
AND bt.is_user_defined = 0
AND t.system_type_id = bt.system_type_id
AND t.user_type_id <> bt.user_type_id
WHERE c.object_id = OBJECT_ID('dbo.your_table_name');
Note that this will return two rows if you use alias types (e.g. CREATE TYPE blat FROM nvarchar(32);). If you really must use those (I recommend against them, also), then change the join clause to:
ON t.is_user_defined = 1
AND bt.is_user_defined = 0
AND t.system_type_id = bt.system_type_id
AND bt.user_type_id = bt.system_type_id
To get the information for all the user-defined types in a database you can use INFORMATION_SCHEMA.DOMAINS:
SELECT
DOMAIN_SCHEMA,
DOMAIN_NAME,
DATA_TYPE,
NUMERIC_PRECISION,
NUMERIC_SCALE,
DATETIME_PRECISION,
CHARACTER_MAXIMUM_LENGTH
FROM
INFORMATION_SCHEMA.DOMAINS
UPD:
The following query return human readable definition for all user defind types:
SELECT
DOMAIN_SCHEMA + '.' + DOMAIN_NAME AS TypeName,
DATA_TYPE +
COALESCE('('+
CAST(COALESCE(NUMERIC_PRECISION,DATETIME_PRECISION,CHARACTER_MAXIMUM_LENGTH) AS VARCHAR) +
COALESCE(',' + CAST(NUMERIC_SCALE AS VARCHAR),'') +
')','') AS Definition
FROM
(
SELECT
DOMAIN_SCHEMA,
DOMAIN_NAME,
DATA_TYPE,
CASE
WHEN DATA_TYPE IN ('tinyint','smallint','int','bigint') THEN NULL
ELSE NUMERIC_PRECISION
END AS NUMERIC_PRECISION,
NUMERIC_SCALE,
CASE
WHEN DATA_TYPE IN ('smalldatetime','datetime','date') THEN NULL
ELSE DATETIME_PRECISION
END AS DATETIME_PRECISION,
CHARACTER_MAXIMUM_LENGTH
FROM
INFORMATION_SCHEMA.DOMAINS
) T
(tested only for types that i am using myself)

SQL Server: Return list of columns shared by a group of database tables

I'm inheriting a large report that we would like to automate. I believe most of the data is in a data warehouse that I can access through SQL Server. The issue I have is that I do not have a lot of documentation (data dictionary, schema, etc.) and I want to determine which fields are common among several tables. Normally, when I want to return a list of tables and columns, I would query the information schema. However, in this case, I'm basically looking for a query that is something like:
select table_name, column_name
from (information_schema, others?)
where table_name like 'T_Blah %'
and column_names are equal
I realize I can get to this through the object browser, but once I start getting into a larger number of tables, I would like a quick query-based approach to identifying my fields for joining.
I appreciate any help I can get. I googled this for a while, but I didn't find a solution (or I was oblivious to the fact that I had found one).
As well as information schema you also have the system table syscolumns. Assuming you use the former, something like this should work:
select column_name, count(distinct table_name)
from information_schema.columns
group by column_name
having count(distinct table_name) > 1
Obviously you could restrict by table name/schema if you wanted to look at a subset
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
If I understood yo correctly, you can try this:
SELECT TABLE_NAME, COLUMN_NAME
FROM ( SELECT *, COUNT(*) OVER(PARTITION BY COLUMN_NAME) Quant
FROM INFORMATION_SCHEMA.COLUMNS) A
WHERE TABLE_NAME LIKE 'T_Blah%' AND Quant > 1
ORDER BY COLUMN_NAME, TABLE_NAME
This should work for sql-server. This is just a query I keep on hand, so it is a little more than you requested. But, I kept it in case you want the extra info :). Just remove it if not.
select distinct columns.name, schemas.name + '.' + tables.name
from sys.columns
join sys.tables
on tables.object_id = columns.object_id
join sys.schemas
on schemas.schema_id = tables.schema_id
where tables.name like '%blah%'
order by columns.name, schemas.name + '.' + tables.name
This will yield the column names and data types in a specified table that also appear in other tables followed by a comma separated list of tables in which they appear:
SELECT COLUMN_NAME, DATA_TYPE, REPLACE(REPLACE(REPLACE(
(SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME = CommonColumns.COLUMN_NAME) AND (DATA_TYPE = CommonColumns.DATA_TYPE)
FOR XML PATH(''))
, '</TABLE_NAME><TABLE_NAME>', ', '), '<TABLE_NAME>', ''), '</TABLE_NAME>', '')
AS Tables
FROM (SELECT DISTINCT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'T_Blah%') AS CommonColumns
WHERE (SELECT COUNT(TABLE_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE (COLUMN_NAME = CommonColumns.COLUMN_NAME) AND (DATA_TYPE = CommonColumns.DATA_TYPE)) > 1
To have it do this for all tables, simply remove the WHERE TABLE_NAME LIKE 'T_Blah%'.
Or as Aaron recommends, avoid INFORMATION_SCHEMA:
SELECT ColumnName, sys.types.name AS DataType, REPLACE(REPLACE(REPLACE(
(SELECT sys.tables.name AS TableName
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.columns.name = CommonColumns.ColumnName) AND
(sys.columns.system_type_id = CommonColumns.system_type_id)
FOR XML PATH(''))
, '</TableName><TableName>', ', '), '<TableName>', ''), '</TableName>', '')
AS Tables
FROM (SELECT DISTINCT sys.columns.name AS ColumnName, sys.columns.system_type_id
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.tables.name LIKE 'T_Blah%')) AS CommonColumns INNER JOIN
sys.types ON sys.types.system_type_id = CommonColumns.system_type_id
WHERE ((SELECT COUNT(sys.tables.object_id) AS TableCount
FROM sys.columns INNER JOIN
sys.tables ON sys.columns.object_id = sys.tables.object_id
WHERE (sys.tables.type = 'U') AND (sys.columns.name = CommonColumns.ColumnName) AND
(sys.columns.system_type_id = CommonColumns.system_type_id)) > 1)
ORDER BY CommonColumns.ColumnName, sys.types.name
To get relations by foreign keys use:
SELECT sys.foreign_keys.name AS ForeignKeyName, OBJECT_NAME(sys.foreign_key_columns.parent_object_id) AS ForeignKeyTableName,
ForeignKeyColumns.name AS ForeignKeyColumnName, OBJECT_NAME(sys.foreign_key_columns.referenced_object_id) AS ReferencedTableName,
ReferencedColumns.name AS ReferencedColumnName
FROM sys.foreign_keys INNER JOIN
sys.foreign_key_columns ON sys.foreign_keys.object_id = sys.foreign_key_columns.constraint_object_id INNER JOIN
sys.columns AS ForeignKeyColumns ON sys.foreign_key_columns.parent_object_id = ForeignKeyColumns.object_id AND
sys.foreign_key_columns.parent_column_id = ForeignKeyColumns.column_id INNER JOIN
sys.columns AS ReferencedColumns ON sys.foreign_key_columns.referenced_object_id = ReferencedColumns.object_id AND
sys.foreign_key_columns.referenced_column_id = ReferencedColumns.column_id
WHERE (OBJECT_NAME(sys.foreign_key_columns.parent_object_id) LIKE 'T_Blah%') OR (OBJECT_NAME(sys.foreign_key_columns.referenced_object_id)
LIKE 'T_Blah%')

SQL Server search for a column by name

I'm doing some recon work and having to dig through a few hundred SQL Server database tables to find columns.
Is there a way to easily search for columns in the database and return just the table name that the column belongs to?
I found this, but that also returns Stored procedures with that column name in it...
SELECT OBJECT_NAME(object_id) FROM sys.columns WHERE name = 'foo'
This includes views though but can be further filtered . It may be useful though.
More generally...
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'foo'
sys.columns
To get the
1) full column name
2) object name (including schema)
3) object type (table/view)
4) data type (nice format: varchar(6) or numeric(5,2), etc.)
5) null/not null
6) information on identity, check constraint, and default info
try this:
DECLARE #Search varchar(200)
SET #Search='YourColumnName' --can be a partial or a complete name
SELECT
s.name as ColumnName
,sh.name+'.'+o.name AS ObjectName
,o.type_desc AS ObjectType
,CASE
WHEN t.name IN ('char','varchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length) END+')'
WHEN t.name IN ('nvarchar','nchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length/2) END+')'
WHEN t.name IN ('numeric') THEN t.name+'('+CONVERT(varchar(10),s.precision)+','+CONVERT(varchar(10),s.scale)+')'
ELSE t.name
END AS DataType
,CASE
WHEN s.is_nullable=1 THEN 'NULL'
ELSE 'NOT NULL'
END AS Nullable
,CASE
WHEN ic.column_id IS NULL THEN ''
ELSE ' identity('+ISNULL(CONVERT(varchar(10),ic.seed_value),'')+','+ISNULL(CONVERT(varchar(10),ic.increment_value),'')+')='+ISNULL(CONVERT(varchar(10),ic.last_value),'null')
END
+CASE
WHEN sc.column_id IS NULL THEN ''
ELSE ' computed('+ISNULL(sc.definition,'')+')'
END
+CASE
WHEN cc.object_id IS NULL THEN ''
ELSE ' check('+ISNULL(cc.definition,'')+')'
END
AS MiscInfo
FROM sys.columns s
INNER JOIN sys.types t ON s.system_type_id=t.system_type_id and t.is_user_defined=0
INNER JOIN sys.objects o ON s.object_id=o.object_id
INNER JOIN sys.schemas sh on o.schema_id=sh.schema_id
LEFT OUTER JOIN sys.identity_columns ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id
LEFT OUTER JOIN sys.computed_columns sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id
LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id
WHERE s.name LIKE '%'+#Search+'%'
select c.name as ColumnName, o.name as TableName
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
where c.name = 'MyColumnName'
http://www.red-gate.com/products/SQL_Search/index.htm?utm_source=google&utm_medium=cpc&utm_content=brand_aware&utm_campaign=sqlsearch&gclid=COSfqe_mmKQCFSE1gwodSxOrEQ
This should do it for you. I use it everyday.
This stored procedure will search for table.name and column.name pairs.
I use when I have "WhateverId" in code and I want to know where that is (probably) stored in the database without actually having to read through and understand the code. :)
CREATE OR ALTER PROC FindColumns
#ColumnName VARCHAR(MAX) = NULL,
#TableName VARCHAR(MAX) = NULL
AS
SELECT T.[name] AS TableName, C.[name] AS ColumnName
FROM sys.all_columns C
JOIN sys.tables T ON C.object_id = T.object_id
JOIN sys.types CT ON C.user_type_id = CT.user_type_id
WHERE (#ColumnName IS NULL OR C.[name] LIKE '%' + TRIM(#ColumnName) + '%')
AND (#TableName IS NULL OR T.[name] LIKE '%' + TRIM(#TableName) + '%')
ORDER BY T.[name], C.[name]
select table_name from information_schema.columns
where column_name = '<your column name here>'
Using the information_schema views is 'more correct' as system details in the system databases are subject to change between implementations of SQL Server.