recreating whole SQL Server Database with relations - sql

i have used SQL server 2012 and made a huge database with many relations. today i realized using "NCHAR" instead on "NVARCHAR" adds space on end of strings which i don't like it. is there any way to recreate database with relations. I've tried "drop and create" for tables but needs to remove all relations and define them again which is very time consuming.

It's possible to alter only the affected tables? like this:
SELECT 'alter table '+s.name+'.'+t.name+
' alter column '+c.name+' nvarchar('+convert(varchar(11),c.max_length/2)+') go'
FROM sys.tables as T
inner join sys.schemas as s
on T.[schema_id]=s.[schema_id]
inner join sys.columns as C
on T.[object_id]=C.[object_id]
and c.system_type_id=239--nchar type
, and before that don't forget to use the same kind of mechanism to generate an update statement to remove extra spaces.

Related

SQL Server - rename and merge databases with legacy support

I have two Sql Server 2008 R2 databases, called MyDbOne and MyDbTwo.
I'd like to merge them (all tables and procedures) into a new database called MyDb.
Assume there are no conflicts in table and procedure names between them.
The problem is: there are LOTS of code and procedures that execute queries using the database name, including procedures declared in one of the databases referecing tables from the other. There are queries like:
select * from MyDbOne..SomeTable;
select * from MyDbTwo..AnotherTable;
The tables SomeTable and AnotherTable would then exist in the MyDb database. But I need to support querying them using the leagcy names MyDbOne and MyDbTwo. If I would run the queries above, I'd like them to be effectively the same as:
select * from MyDb..SomeTable;
select * from MyDb..AnotherTable;
Is there some way to do it? Maybe create some sort of global aliases on the new database, resolving MyDbOne and MyDbTwo to MyDb? That would be perfect, but I don't know how to do it.
Thank you ver much!
There's no easy way around it. You'll have to update all those references manually. You can search the SQL server for all objects containing those database names by using one of these queries from this answer;
SELECT ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%Foo%'
AND ROUTINE_TYPE='PROCEDURE'
SELECT OBJECT_NAME(id)
FROM SYSCOMMENTS
WHERE [text] LIKE '%Foo%'
AND OBJECTPROPERTY(id, 'IsProcedure') = 1
GROUP BY OBJECT_NAME(id)
SELECT OBJECT_NAME(object_id)
FROM sys.sql_modules
WHERE OBJECTPROPERTY(object_id, 'IsProcedure') = 1
AND definition LIKE '%Foo%'
I don't think there is an issue solution to this. If I were you, I would keep existing MyDbOne and MyDbTwo databases intact and create a brand new one that references these two tables via views. Basically, you will create a Data Warehouse that seats on top of these existing databases. Good thing about this setup is, you don't have to rewrite any legacy code, which is huge.

Altering the Data Type of Table and View

I am having a big database with lots of view and tables.
now in many tables and views the datatype of column , named 'Company' is INT
with time the data changed and now we want 'Company' column to hold character value.
Can I write a cursor to change the datatype of all this tables and Views, Because manually changing the datatype is time consuming.
I tried modifying datatype with the help of this link: How to Change All Sql Columns of One DataType into Another
But this is working only for table , I am not able to change the datatype of Views
Thanks in advance for your help!
If you do not see the correct data type in your views, then you need to recompile them. SQL Server is not very smart about invalidating views if dependent objects change. E.g. if you have a view that select * (which you anyways should not do) from a table and you add a column, the view will not reflect the new column until you recompile it. The same is true for other changes to dependent objects.
To recompile the view use the stored procedure sp_refreshview. This MSDN page describes the procedure and also has a script at the bottom of the page that allows you to bulk refresh all your views.
First of all, you don't need to modify anything in view. Any change in corresponding table will automatically reflect in your view.
If not, it might be because if a view is not created with schemabinding, sp_refreshview should be run when changes are made to the objects underlying the view that affect the definition of the view. Otherwise, the view might produce unexpected results when it is queried. SO as suggested by #Ralf, I +1 that answer, use sp_refreshview to update view.
For your comment ALTER TABLE ALTER COLUMN Company failed because one or more objects access this column. This is because some constraint or index is using that column you have to first drop that and then only you might be able to alter that column.
You can find related constraint using query:
select db_name() as CONSTRAINT_CATALOG
,t_obj.name as TABLE_NAME
,user_name(c_obj.uid) as CONSTRAINT_SCHEMA
,c_obj.name as CONSTRAINT_NAME
,col.name as COLUMN_NAME
,col.colid as ORDINAL_POSITION
,com.text as DEFAULT_CLAUSE
from sysobjects c_obj
join syscomments com on c_obj.id = com.id
join sysobjects t_obj on c_obj.parent_obj = t_obj.id
join sysconstraints con on c_obj.id = con.constid
join syscolumns col on t_obj.id = col.id
and con.colid = col.colid
where
c_obj.uid = user_id()
Drop any index and/or constraint on column & then try alter, it must work then.
Also refer answers to this question Drop a column from table problem (SQL Server 2008)
Hope it helps.

How do I get a list of columns in a table or view?

On occasion, I'm interested in getting a list of columns in one of the tables or views in my SQL Server 2008 R2 database. It's useful, for example, if you're building database documentation without using an expensive off-the-shelf product.
What's an easy way to get this information?
In SQL Server 2008 R2 (among other versions), there are system views provided automatically with every database. As long as you are connected to the database where your table resides, you can run a query like this:
DECLARE #TableViewName NVARCHAR(128)
SET #TableViewName=N'MyTableName'
SELECT b.name AS ColumnName, c.name AS DataType,
b.max_length AS Length, c.Precision, c.Scale, d.value AS Description
FROM sys.all_objects a
INNER JOIN sys.all_columns b
ON a.object_id=b.object_id
INNER JOIN sys.types c
ON b.user_type_id=c.user_type_id
LEFT JOIN sys.extended_properties d
ON a.object_id=d.major_id AND b.column_id=d.minor_id AND d.name='MS_Description'
WHERE a.Name=#TableViewName
AND a.type IN ('U','V')
Of course, this is just a starting point. There are many other system views and columns available in every database. You can find them through SQL Server Management Studio under Views > "System Views
Another way is querying the INFORMATION_SCHEMA.columns view as detailed here:
Information_Schema - COLUMNS
This will give you information for all the columns in the current database (and what table/view they belong to) including their datatypes, precision, collation and whether they allow nulls etc
Usefully as well, these views are maintained in multiple DBMS programs too, so you could potentially use the same or similar query to get the same information regarding a MySQL database as you can a SQL Server DB, which could be useful if you are developing on multiple platorms.
sp_columns returns detailed information about each of the columns in the table. SO Answer
sp_columns #tablename
sp_help returns detailed information about the entire table including the columns and constraints. SO Answer
sp_help #tablename
To get a list of Columns of a view with some other information about the column you can use the following:
SELECT * FROM sys.columns c, sys.views v
WHERE c.object_id = v.object_id
AND v.name = 'view_Name'
GO
And if you only want the list of Column Name use this.
SELECT c.name
FROM sys.columns c, sys.views v
WHERE c.object_id = v.object_id
AND v.name = 'view_UserAssessphers'
GO
exec sp_helptext <your view name>
Also works for the view only, blachniet's answer is best if you need details on the columns in the table.
In a new query window, type the name of the view/table, highlight it, and press Alt-F1. This will run sp_help, like blachniet suggested.
simple list of column names without any further information.
SELECT COLUMN_NAME FROM TABLENAME.INFORMATION_SCHEMA.COLUMNS;
Replace TABLENAME with your tables name.

How to find which views are using a certain table in SQL Server (2008)?

I have to add a few columns to a table and I also need to add these columns to all the views that use this table.
Is it possible to get a list of all the views in a database that use a certain table?
This should do it:
SELECT *
FROM INFORMATION_SCHEMA.VIEWS
WHERE VIEW_DEFINITION like '%YourTableName%'
To find table dependencies you can use the sys.sql_expression_dependencies catalog view:
SELECT
referencing_object_name = o.name,
referencing_object_type_desc = o.type_desc,
referenced_object_name = referenced_entity_name,
referenced_object_type_desc =so1.type_desc
FROM sys.sql_expression_dependencies sed
INNER JOIN sys.views o ON sed.referencing_id = o.object_id
LEFT OUTER JOIN sys.views so1 ON sed.referenced_id =so1.object_id
WHERE referenced_entity_name = 'Person'
You can also try out ApexSQL Search a free SSMS and VS add-in that also has the View Dependencies feature. The View Dependencies feature has the ability to visualize all SQL database objects’ relationships, including those between encrypted and system objects, SQL server 2012 specific objects, and objects stored in databases encrypted with Transparent Data Encryption (TDE)
Disclaimer: I work for ApexSQL as a Support Engineer
If you need to find database objects (e.g. tables, columns, triggers) by name - have a look at the FREE Red-Gate tool called SQL Search which does this - it searches your entire database for any kind of string(s).
It's a great must-have tool for any DBA or database developer - did I already mention it's absolutely FREE to use for any kind of use??
I find this works better:
SELECT type, *
FROM sys.objects
WHERE OBJECT_DEFINITION(object_id) LIKE '%' + #ObjectName + '%'
AND type IN ('V')
ORDER BY name
Filtering VIEW_DEFINTION inside INFORMATION_SCHEMA.VIEWS is giving me quite a few false positives.
SELECT VIEW_NAME
FROM INFORMATION_SCHEMA.VIEW_TABLE_USAGE
WHERE TABLE_NAME = 'Your Table'
select your table -> view dependencies -> Objects that depend on
Simplest way to find used view or stored procedure for the tableName using below query -
exec dbo.dbsearch 'Your_Table_Name'

SQL: use computed string as table name, join all rows of select for counting

I have access to a MS SQL Server with MS Access via ODBC and I want to display the table names, their column names and the number of rows per table. The table names are stored in a table named "sys_tables", the column names in "sys_columns". Unfornunately the number of rows per table has to be counted. As I'm not experienced in SQL, my first try is not working:
SELECT t.name, c.name, t.object_id, x.cnt
FROM sys_tables AS t INNER JOIN sys_columns AS c ON t.object_id = c.object_id
LEFT OUTER JOIN (SELECT COUNT(*) AS cnt FROM #t.name AS tbl ON tbl.cnt > 0) AS x
What is the right way to use a computed string in a SELECT as table name? Can I do a sub select that selects all rows without real relation?
You can't use a variable table name in a SQL statement on the server side. You will need to get the table names from SQL Server and then use those to send new queries (one for each table) back to SQL Server. You could also write a stored procedure on the SQL Server to handle this using dynamic SQL (just be sure that you are familiar with injection attacks whenever you are using dynamic SQL).
SQL Server stores some row count information in sysindexes (not to be confused with sys.indexes) in the rowcnt column. This information is not always 100% accurate though.
Finally, you can use the undocumented stored procedure sp_MSForEachTable like so:
EXEC sp_msForEachTable
'SELECT PARSENAME(''?'', 1),
COUNT(*) FROM ?'
Be aware that this last method will return multiple result sets (one for each table), so you need to handle it that way in Access or combine them together in a temporary table and then return them as one result set. You can do all of that in a stored procedure.
You cannot use a variable for a table name. The only workaround is dynamic SQL.
However, I suspect that there's a table somewhere in sys which gives the row count for each table, though it may not be kept perfectly up-to-date.
Can't you do this:
SELECT COUNT(t.name)
FROM sys_tables AS t INNER JOIN sys_columns AS c ON t.object_id = c.object_id