When we need the query of stored procedures we use 'Sp_Helptext procedurename'
Can something similar be done for tables?
Use Alt+F1 while table name selected in a query window.
Pretty Simple :
sp_help YourTable
Please use followig query
select * from information_Schema.columns where table_name = 'TableName'
There does not appear to be a direct equivalent of sp_helptext that will work with tables.
The two methods that seem to be common on various message boards are:
Use Information_Schema.Columns and concatenate the results into the create statement.
Use SQL-DMO script
There is an article on the second method here
Try with this SP. It doesn't have all the notations required for a table like primary keys and foreign keys but is a start.
CREATE PROCEDURE [dbo].[GeneradorTablas]
#Tabla AS VARCHAR(100)
AS
BEGIN
DECLARE #Script AS VARCHAR(MAX) ='CREATE TABLE [dbo].[' + #Tabla + '](' + CHAR(13)
DECLARE #Columnas As TABLE(indice INT, Columna VARCHAR(1000))
INSERT INTO #Columnas
SELECT
ROW_NUMBER()OVER(ORDER BY C.column_id),
' [' + C.name + '] [' + TY.name + ']' +
CASE WHEN
TY.name='nvarchar' OR
TY.name='nchar' OR
TY.name='char' OR
TY.name='varbinary' OR
TY.name='varchar' OR
TY.name='text' THEN
'(' + CASE WHEN C.max_length>0 THEN CAST(C.max_length AS VARCHAR(10)) ELSE 'MAX' END + ')' ELSE ''
END +
CASE WHEN C.is_identity=1 THEN ' IDENTITY(1,1)' ELSE '' END +
' ' + CASE WHEN C.is_nullable=1 THEN 'NULL' ELSE 'NOT NULL' END + ','
FROM SYS.COLUMNS AS C
INNER JOIN SYS.TYPES AS TY ON C.system_type_id=TY.system_type_id
INNER JOIN SYS.TABLES AS T ON C.object_id=T.object_id
WHERE T.name=#Tabla
DECLARE #i AS INT
SELECT #i=MIN(indice) FROM #Columnas
WHILE #i IS NOT NULL
BEGIN
SELECT #Script+=Columna+CHAR(13) FROM #Columnas WHERE indice=#i
SELECT #i=MIN(indice) FROM #Columnas WHERE indice>#i
END
SET #Script=SUBSTRING(#Script,0,LEN(#Script)-1) + CHAR(13) + ')'
PRINT #Script
END
GO
review dba tools which can be installed as add on in powershell https://docs.dbatools.io/Get-DbaDbTable
will give you results in line like this
enter image description here
Related
For example this is my ID: 07E485
I need to find this ID in all tables wherever it is found
All columns, which might carry this value, are sort of string-type...
Something like: select * from **alltables** where **anyColumn**='07E485'
The following query will return all tables in the database yourDBName whose name contains 07E485.
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND
TABLE_CATALOG = 'yourDBName' AND
TABLE_NAME LIKE '%07E485%'
If I misread your requirement, and you instead wanted to find all tables precisely named 07E485 in any database, then you can use the following query:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE' AND
TABLE_NAME = '07E485'
In each database you have a view called INFORMATION_SCHEMA.COLUMNS, you can use this view to query through all of your tables.
This is the way I'ld do it, if anyone know a better way, feel free.. :)
SET NOCOUNT ON
DECLARE #Table varchar(255), #Schema varchar(255), #SQL varchar(MAX)
DECLARE table_cursor CURSOR FOR
SELECT TABLE_NAME, TABLE_SCHEMA
FROM INFORMATION_SCHEMA.COLUMNS -- This is a system view where you can see all columns of a database.
WHERE UPPER(COLUMN_NAME) = 'ID' -- This makes sure you don't loop through any tables that don't have a Column called 'ID'.
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO #Table, #Schema
WHILE ##FETCH_STATUS = 0 BEGIN
-- This part creates your queries.
SET #SQL = 'SELECT * FROM '+#Schema+'.'+#Table+'
WHERE CAST(ID as varchar) = ''07E485''' -- Casting ID to varchar to avoid data type errors.
-- This executes the query.
EXEC(#SQL)
-- If a result is found, i.e. ID is equal to '07E485' somewhere in the table, Table name is printed on the "Messages" tab.
IF ##ROWCOUNT > 0 PRINT #Table
FETCH NEXT FROM table_cursor INTO #Table, #Schema
END
CLOSE table_cursor
DEALLOCATE table_cursor
To see which tables contain id = '07E485', go to "Messages" and you will have a list of them.
UPDATE My answer completely re-written
Try it like this: This dynamic SQL will check all string-type columns if they are equal to the given search string. You might want to add more data types to the output to get a better look onto the table's row. But one cannot simply put SELECT * as there are data types not allowed in XML without extra effort.
Secondly, by using QUOTENAME, I avoid syntax errors due to column or table names with blanks...
DECLARE #Search VARCHAR(10)='07E485';
DECLARE #cmd VARCHAR(MAX);
WITH TableNames AS
(
SELECT t.*
,t.TABLE_CATALOG + '.' + t.TABLE_SCHEMA + '.' + t.TABLE_NAME AS FullTblName
,QUOTENAME(t.TABLE_CATALOG)+ '.' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) AS FullTblNameQuoted
,
STUFF(
(
SELECT 'OR ' + QUOTENAME(c.COLUMN_NAME) + '=''' + #Search + ''' '
FROM INFORMATION_SCHEMA.COLUMNS AS c
WHERE c.TABLE_CATALOG=t.TABLE_CATALOG AND c.TABLE_SCHEMA=t.TABLE_SCHEMA AND c.TABLE_NAME=t.TABLE_NAME
AND DATA_TYPE LIKE '%char%' --add more types if needed
FOR XML PATH('')
),1,3,'') AS WhereFilter
FROM INFORMATION_SCHEMA.TABLES AS t
WHERE TABLE_TYPE='BASE TABLE'
)
SELECT #cmd = STUFF(
(
SELECT DISTINCT 'UNION ALL SELECT (SELECT ' + (SELECT STUFF((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS AS c
WHERE c.TABLE_CATALOG=TableNames.TABLE_CATALOG
AND c.TABLE_NAME =TableNames.TABLE_NAME
AND c.DATA_TYPE LIKE '%char%'
FOR XML PATH('')),1,1,'')) + ' FROM ' + FullTblNameQuoted
+ ' WHERE ' + WhereFilter
+ ' FOR XML PATH(''row''),ROOT(''' + REPLACE(REPLACE(FullTblName,'.','_'),' ','') + '''),TYPE) AS XmlData '
FROM TableNames
WHERE WhereFilter IS NOT NULL
FOR XML PATH('')
),1,10,'')
SET #cmd='SELECT XmlData FROM(' + #cmd + ') AS tbl WHERE XmlData IS NOT NULL;'
PRINT LEN(#cmd)
EXEC(#cmd)
Is there a possibility to alter a column from "allows null" to "does not allow null" without knowledge of the actual data type of the column?
I think no, so I have made as the basic skeleton code for my stored procedure:
SELECT t.name,c.max_length FROM sys.types t
LEFT JOIN sys.columns c ON(t.system_type_id = c.system_type_id)
WHERE object_id=OBJECT_ID(#TableName) AND c.name=#FieldName;
and
EXEC('UPDATE ' + #TableName + ' SET ' + #FieldName + ' = ' + #DefaultValue + ' WHERE ' + #FieldName + ' IS NULL');
EXEC('ALTER TABLE ' + #TableName + ' ALTER COLUMN ' + #FieldName + ' NOT NULL');
I guess now I only have to get the return values from the first query back into the second. I can't get my head around how to get the values into a variable and then access them again. Ideas?
Since the INFORMATION_SCHEMA has all required information and is part of a SQL standard, it might be better to use that in this case (however, SQL Server's ALTER TABLE ALTER COLUMN is non-standard anyway so it might not matter as much).
Either way, you should also be checking for whether there's character length and/or numeric precision being specified, and make sure you're altering the table in the correct schema (and not getting dbo.TableName instead of customschema.TableName). You could try something like this (I used INFORMATION_SCHEMA here but you could easily refactor this to use the sys.columns view):
DECLARE #retVal VARCHAR(500);
SELECT #retVal =
CASE WHEN CHARACTER_MAXIMUM_LENGTH > 0
THEN CONCAT(DATA_TYPE, '(', CHARACTER_MAXIMUM_LENGTH ,')')
WHEN CHARACTER_MAXIMUM_LENGTH = -1 AND DATA_TYPE <> 'xml'
THEN CONCAT(DATA_TYPE, '(MAX)')
WHEN DATA_TYPE IN ('numeric', 'decimal')
THEN CONCAT(DATA_TYPE, '(', NUMERIC_PRECISION,',', NUMERIC_SCALE,')')
ELSE DATA_TYPE
END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #schemaName
AND TABLE_NAME = #tableName
AND COLUMN_NAME = #columnName
#retVal will now capture datatypes like int, varchar(100), varbinary(MAX), or decimal(10,2) correctly.
And then build up a dynamic SQL Query like this:
DECLARE #sql VARCHAR(MAX);
SET #sql = 'ALTER TABLE ' + #schemaName + '.' + #tableName + ' ALTER COLUMN ' + #columnName + ' ' + #retVal + ' NOT NULL;'
EXEC(#sql);
You select values into variables like this:
SELECT #Var1=t.name,#Var2=c.max_length FROM sys.types t
LEFT JOIN sys.columns c ON(t.system_type_id = c.system_type_id)
WHERE object_id=OBJECT_ID(#TableName) AND c.name=#FieldName;
This of course assumes that you have already declared Var1 & Var2, and that your query will only return one row.
I want to delete the ABCDEF column from all tables of my database. I am trying this code:
declare #SQL nvarchar(max)
SELECT
#SQL = STUFF((SELECT ' DROP column ' + quotename(TABLE_SCHEMA) + '.' + quotename(table_NAME ) +'.ABCDEF;'
FROM
information_schema.columns
FOR XML PATH('')),1,2,'')
PRINT #SQL
EXECUTE (#SQL)
But I am getting an error
incorrect syntax near column
How to do this?
You can use an undocumented feature of SQL Server sys.sp_msforeachtable. The below script will basically iterate for all the tables in database and alter them if required.
select '[dbo].['+tab.name+']' name into #table from
sys.tables tab join sys.columns col on tab.object_id = col.object_id and col.name = 'ABCDEF'
exec sys.sp_msforeachtable 'if exists (select 1 from #table where name = ''?'')
alter table ? drop column [ABCDEF]'
That's not the right way to drop a column from a table. It should be
ALTER TABLE table_name DROP COLUMN column_name
Build your dynamic query something like this:
DECLARE #sql NVARCHAR(max)=''
SELECT #SQL += 'Alter table ' + Quotename(table_catalog)
+ '.' + Quotename(table_schema) + '.'
+ Quotename(TABLE_NAME) + ' DROP column '
+ Quotename(column_name) + ';'
FROM information_schema.columns where COLUMN_NAME = 'abcd' -- Here alone mention
--the Column to be removed
EXEC Sp_executesql #sql
While dropping the columns from multiple tables, I faced following default constraints error.
The object 'DF_TableName_ColumnName' is dependent on column 'ColumnName'.
To resolve this, I have to drop all those constraints first, by using following query
DECLARE #sql NVARCHAR(max)=''
SELECT #SQL += 'Alter table ' + Quotename(tbl.name) + ' DROP constraint ' + Quotename(cons.name) + ';'
FROM SYS.DEFAULT_CONSTRAINTS cons
JOIN SYS.COLUMNS col ON col.default_object_id = cons.object_id
JOIN SYS.TABLES tbl ON tbl.object_id = col.object_id
WHERE col.[name] IN ('Column1','Column2')
--PRINT #sql
EXEC Sp_executesql #sql
After that, I dropped all those columns by using the answer above.
DECLARE #sql NVARCHAR(max)=''
SELECT #SQL += 'Alter table ' + Quotename(table_catalog)+ '.' + Quotename(table_schema) + '.'+ Quotename(TABLE_NAME)
+ ' DROP column ' + Quotename(column_name) + ';'
FROM information_schema.columns where COLUMN_NAME IN ('Column1','Column2')
--PRINT #sql
EXEC Sp_executesql #sql
I posted here in case someone find the same issue.
Happy Coding!
I have a procedure that does a "select * from view" and this output contains an inverted comma in one of the columns. I want to do a replace() to remove the extra inverted comma but I cannot change the "select *" as this is a dynamic query that is used in different scenarios.
As evident, the following query does not work
select replace(*, '"', '') from ReportRegistry
Some help appreciated.
I wanted to know if there is any way I can remove the quotes without knowing the column names. I want them to be removed from all columns. The columns names are different in different cases.
The view is defined within the procedure differently in different cases. The dynamic colum names are added as text and them executed using sp_executesql.
DECLARE #ColNames NVARCHAR(MAX) = ''
--Dynamically build a list of column names for the view, separated by commas.
SELECT #ColNames = #ColNames +
CASE
--Use the REPLACE function for "String" type data types. Did I leave any data types out?
--Change "x" to the character(s) you want to replace.
WHEN c.DATA_TYPE IN ('VARCHAR', 'CHAR', 'NVARCHAR', 'NCHAR') THEN 'REPLACE([' + c.COLUMN_NAME + '], ''x'', '''') AS [' + c.COLUMN_NAME + '],'
--All other data types.
ELSE '[' + c.COLUMN_NAME + '],'
END
--In addition to user tables, views are included in INFORMATION_SCHEMA.COLUMNS (and in INFORMATION_SCHEMA.TABLES).
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = 'ReportRegistry'
--Retain original order of the view's columns.
ORDER BY c.ORDINAL_POSITION
--Remove last comma
SET #ColNames = LEFT(#ColNames, LEN(#ColNames) - 1)
EXEC ('SELECT ' + #ColNames + ' FROM ReportRegistry ')
select replace(TargetColumnName, '"', '')
,Column2
,Column3
,..... and so on.....
from ReportRegistry
declare #tbl varchar(max) = 'table_or_view_name'
declare #cols varchar(max) =
(select case when data_type='varchar' then 'REPLACE('+column_name+',''"'','''')' else column_name end+char(10)+','
from information_schema.columns
where table_name = #tbl for xml path(''))
declare #sql varchar(max)='select '+left(#cols,len(#cols)-1)+' from '+#tbl
print #sql
exec(#sql)
I was wondering if there is an equivalent in SQL Server 2008 to Oracle's DBMS_METADATA.GET_DDL Function? You can pass this function a table name and it will return the ddl for that table so that you can use it to build a script for a schema.
I know I can go into SSMS and use that, but I would prefer to have a t-sql script that would generate the ddl for me.
Thanks,
S
I using this query for generate query but this work for 1 table :
declare #vsSQL varchar(8000)
declare #vsTableName varchar(50)
select #vsTableName = 'Customers'
select #vsSQL = 'CREATE TABLE ' + #vsTableName + char(10) + '(' + char(10)
select #vsSQL = #vsSQL + ' ' + sc.Name + ' ' +
st.Name +
case when st.Name in ('varchar','varchar','char','nchar') then '(' + cast(sc.Length as varchar) + ') ' else ' ' end +
case when sc.IsNullable = 1 then 'NULL' else 'NOT NULL' end + ',' + char(10)
from sysobjects so
join syscolumns sc on sc.id = so.id
join systypes st on st.xusertype = sc.xusertype
where so.name = #vsTableName
order by
sc.ColID
select substring(#vsSQL,1,len(#vsSQL) - 2) + char(10) + ')'
If you are looking for a TSQL solution, it is quite verbose, as [this example]¹ shows.
A shorter alternative would be using the SMO library (example)
¹ Link for this example deleted. The way Internet Archive Wayback Machine displayed an error saying that they could not display the content. And following the link to the original went someplace malicious. (Grave errors, instruction to call some number, etc.)