Orphan constraints in SQL Server database - sql-server

Running the following query results in all constraints in our client's database. However, several rows in the result set don't seem to have a parent, i.e. parent_object_id = 0 and OBJECT_NAME(parent_object_id) returns NULL.
SELECT name, type_desc, OBJECT_NAME(parent_object_id), parent_object_id
FROM sys.objects
WHERE is_ms_shipped = 0
AND type_desc LIKE '%_CONSTRAINT'
Does this mean there are orphan constraints in the database? If so, how do I remove these?
From their names, I can see they are leftovers from before a large amount changes were made to the structure.

Using sp_helptext I can see they were created using a CREATE DEFAULT statement, e.g.:
CREATE DEFAULT dbo.MyDefault AS 2
This means they are simply unbound defaults, which can be bound using the sp_binddefault according to MSDN, and removed with a simple DROP DEFAULT statement:
DROP DEFAULT dbo.MyDefault
I wasn't aware of this syntax, which apparently will be removed in a future version of SQL Server, according to the aforementioned MSDN article.

Related

Where are views stored in SQL Server

I'm a SQL Server newbie. I've tried foraging around on the web for a while but could not get my question answered. Can anyone please tell me where exactly is a view stored in SQL server 2008 database?
The pedantic answer to your question is... only Microsoft knows exactly where view metadata is physically stored. In the move from SQL 2000 to SQL 2005 (on which 2008 is based) MS got rid of direct access to system tables where views used to be literally stored (dbo.sysviews and dbo.syscomments) and added a layer of abstraction (via the hidden resources database) which means you can only access meta data about views via catalog views. INFORMATION_SCHEMA is an ANSI compliant set of catalog views. While marginally useful for their relative portability between versions, often more information is available from the sql 2008 catalog views - in this case sys.views and sys.sql_modules
Be aware that views can be created with the ENCRYPTION option set which encrypts the sys.comments record(s) that contain the SQL definition of the view. But if not encrypted, then sp_helptext [MyView] will give you a quick look at the definition.
edited as per 1st comment below, to replace "sys.comments" with "sys.sql_modules"
Note: Based on this post
http://improve.dk/archive/2012/08/27/where-does-sql-server-store-the-source-for-stored-procedures.aspx, is very likely that the definition of views are stored (also) in sys.sysobjvalues system table.
The list of all user T-SQL modules (within SQL Server 2008) can be queried using sys.sql_modules system view (link). Here, you can find the definitions of user views (column definition):
SELECT QUOTENAME(s.name)+'.'+QUOTENAME(o.name) AS full_object_name,
m.*
FROM sys.sql_modules m
JOIN sys.objects o ON m.object_id=o.object_id
JOIN sys.schemas s ON o.schema_id=s.schema_id
WHERE o.type='V' -- only view objects
ORDER BY full_object_name
If you run EXEC sp_helptext 'sys.sql_modules' you will get the source code of this system view:
CREATE VIEW sys.sql_modules AS
SELECT object_id = o.id,
definition = object_definition(o.id),
uses_ansi_nulls = sysconv(bit, o.status & 0x40000), -- OBJMOD_ANSINULLS
uses_quoted_identifier = sysconv(bit, o.status & 0x80000), -- OBJMOD_QUOTEDIDENT
is_schema_bound = sysconv(bit, o.status & 0x20000), -- OBJMOD_SCHEMABOUND
uses_database_collation = sysconv(bit, o.status & 0x100000), -- OBJMOD_USESDBCOLL
is_recompiled = sysconv(bit, o.status & 0x400000), -- OBJMOD_NOCACHE
null_on_null_input = sysconv(bit, o.status & 0x200000), -- OBJMOD_NULLONNULL
execute_as_principal_id = x.indepid
FROM sys.sysschobjs o
LEFT JOIN sys.syssingleobjrefs x ON x.depid = o.id AND x.class = 22 AND x.depsubid = 0 -- SRC_OBJEXECASOWNER
WHERE o.pclass <> 100
AND ((o.type = 'TR' AND has_access('TR', o.id, o.pid, o.nsclass) = 1)
OR (type IN ('P','V','FN','IF','TF','RF','IS') AND has_access('CO', o.id) = 1)
OR (type IN ('R','D') AND o.pid = 0))
You can see that this view queries another system object sys.sysschobjs that, I think, is the system table used to store definition of views.
Note 1: Using INFORMATION_SCHEMA.VIEWS to find definition of a view is not a reliable method because INFORMATION_SCHEMA.VIEWS.VIEW_DEFINITION column definition is convert(nvarchar(4000), object_definition(object_id)) (max. 4000 chars).
Note 2: Instead, you should use sys.sql_modules.definition column: definition = object_definition(o.id). If you look at object_definition function (link) you will see that return type is nvarchar(max).
If you mean the tables the view produces then the answer is that they aren't stored at all. A view is just a query, and that is all it stores. When you query a view the db engine just fetches your view query's results and then queries those.
DB engines can store 'materialized' views, but that's a different topic.
In a system table.
The following query will retrieve them...
SELECT TABLE_NAME as ViewName,
VIEW_DEFINITION as ViewDefinition
FROM INFORMATION_SCHEMA.Views
To view edit them normally you would look in the view folder under tables in studio manager.
You can create/edit them from this folder using the designer or write scripts.
View is a simple SQL statement that is stored in database schema (INFORMATION_SCHEMA.Views). So when ever we call the view the SQL statement gets executed and return the rows from main physical table.
You can also tell the view as a Logical table that store the defination (the sql statement) but not the result.
You can see the defination using below statement, as said by Dan above, Only if the view defination is Not encrypted:
SELECT TABLE_NAME as ViewName, VIEW_DEFINITION as ViewDefinition FROM INFORMATION_SCHEMA.Views
More details on View # MSDN.

SQL Server - Querying sysobjects

I notice that when I query dbo.sysobjects, to determine all the objects in my database, it also picks up all system views whose name starts with 'syncobj_'. These have an xtype of 'V' and there doesn't appear to be any way I can know these are system views, and not my own, except by examining the name of the view. Is there some other way? I would like to exclude these from a query I'm in the process of creating.
See OBJECTPROPERTY:
IsMSShipped
Any schema-scoped object
Object created during installation of SQL Server. 1 = True 0 = False
Use it something like:
SELECT * from sysobjects where OBJECTPROPERTY(ID,N'IsMSShipped') = 0
It's documentation is a bit off though - it also assists you with excluding other objects added "by" SQL Server at a later date also - e.g. any replication related objects are also considered to be IsMSShipped.
Try something like:
select *
from sysobjects
where name NOT IN (
select name from sys.system_views
)
Since you are using SQL Server 2008, there is very little reason to continue using the outdated compatibility view sysobjects. You should instead use the catalog view sys.objects, introduced in SQL Server 2005. As an added bonus, you don't need to call an external OBJECTPROPERTY() function for every single row, since it contains a column called is_ms_shipped that reveals the same information.
SELECT OBJECT_SCHEMA_NAME([object_id]), name, type
FROM sys.objects
WHERE is_ms_shipped = 0;

How can I compare tables in two different databases using SQL?

I'm trying to compare the schemas of two tables that exist in different databases. So far, I have this query
SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('table1')
The only thing is that I don't know how to use the sys.columns to reference a database other than the one that the query is connected to. I tried this
SELECT * FROM db.sys.columns WHERE object_id = OBJECT_ID('table1')
but it didn't find anything.
I'm using SQL Server 2005
Any suggestions? thanks!
Take a look at redgate's SQL Compare.
To answer your specific question, you need to fully qualify the table reference.
SELECT * FROM db.sys.columns WHERE object_id = OBJECT_ID('db.SchemaName.table1')
Late one but hopefully useful.
Even though chama asked for SQL solutions I’d still recommend using a third party tools such as ApexSQL Diff or tools from Red Gate Joe already mentioned (I’ve used both and they worked great).
Reason is that query for comparing two tables using information schema has to be quite complex in order to catch all differences.
Note that all of the examples mentioned here only cover columns but none of the queries shown here will show the difference between nvarchar(20) and nvarchar(50) or difference in foreign keys or indexes or….
Short answer is yes – this is possible using information schema views but it can be rather complex if you want to compare every detail in those two tables.
all you need is to specify the DB name and shcema when calling OBJECT_ID function, like:
SELECT *
FROM DB_NAME.sys.columns
WHERE object_id = OBJECT_ID('DB_NAME.SHCEMA_NAME.table1')
Try the information_schema. eg:
select *
from
db1.information_schema.columns col1
join db2.information_schema.columns col2
on col1.table_catalog = col2.table_catalog
and col1.table_schema = col2.table_schema
and col1.column_name = col2.column_name
...
The information_schema simplifies sticking together the information from all the sys.columns,sys.objects etc. It exists automatically in your DB. I think its actually an ISO standard thing, so should work on various DB systems.
More information about the information_schema can be found here
Comparing whether the object or columns exists in both schemas is only a tiny bit of the solution. What if they exist in both databases but are different?
For my bsn ModuleStore project, I implemented a scripting routine which actually scripts most DB objects including table and view columns, indexes, namespaces etc. as XML using T-SQL code only. This may be a good place to start. You can find it on Google code, and the file in question (which generates the SQL query for dumping the object schema to XML) is here.
Code -
drop table #a
drop table #b
select *
into #a
from [databasename1].information_schema.columns a
--where table_name = 'aaa'
select *
into #b
from [databasename2].information_schema.columns b -- add linked server name and db as needed
--where table_name = 'bbb'
select distinct( a.table_name), b.TABLE_SCHEMA+ '.' + (b.table_name) TableName,b.TABLE_CATALOG DatabaseName
from #a a
right join #b b
on a.TABLE_NAME = b.TABLE_NAME and a.TABLE_SCHEMA = b.TABLE_SCHEMA
where a.table_name is null-- and a.table_name not like '%sync%'
Just in case you are using MS VS 2015 (Community is a free download). The SOL Server tools includes a Schema Comparison tool. "SQL Server Data Tools (SSDT) includes a Schema Compare utility that you can use to compare two database definitions".
This is a GPL Java program I wrote for comparing data in any two tables, with a common key and common columns, across any two heterogeneous databases using JDBC: https://sourceforge.net/projects/metaqa/
It intelligently forgives (numeric, string and date) data type differences by reducing them to a common format. The output is a sparse tab delimited file with .xls extension for use in a spreadsheet.
The program ingests SQL that is used to produce a source table that can be compared with the target table. The target table SQL can be generated automatically. The target table is read one row at a time and therefore should be indexed on the common key.
It detects missing rows on either side and common keyed rows with other optional column differences. Obviously the meta data can be accessed by SQL so whether your concern is with the data, or with the meta-data, it will still work.
This is very powerful in a data migration or System migration project, and also for auditing interfaces. You will be astounded at the number of errors it detects. Minimal false positives still do occur.
Informix, Oracle and SQL-Server were the first JDBC targets and you can extend that list if desired.

Is there a way to retrieve the view definition from a SQL Server using plain ADO?

I'm successfully extracting column definitions from databases hosted on a SQL server using the ADO Connection OpenSchema() call in its various incarnations so I can programmatically recreate those tables in another SQL database. So far, so good.
The main interaction with the above tables happens using multiple views; while OpenSchema() is able to return the column definitions for the view in the same way that it returns column definitions for a table, a crucial bit of information is missing - which table and column in the underlying tables the column in the view maps to.
I tried to access the SQL command used to create the view using ADOX Catalog Views, but it appears that the OLEDB driver for SQL Server that we're using doesn't support this functionality.
Is there any way to get at this information for the view configuration via ADO, either in a way that states "ColumnX maps to ColumnY in table Z" or in the form of the actual SQL command used to create the view?
Which version of SQL Server?
For SQL Server 2005 and later, you can obtain the SQL script used to create the view like this:
select definition
from sys.objects o
join sys.sql_modules m on m.object_id = o.object_id
where o.object_id = object_id( 'dbo.MyView')
and o.type = 'V'
This returns a single row containing the script used to create/alter the view.
Other columns in the table tell about about options in place at the time the view was compiled.
Caveats
If the view was last modified with ALTER VIEW, then the script will be an ALTER VIEW statement rather than a CREATE VIEW statement.
The script reflects the name as it was created. The only time it gets updated is if you execute ALTER VIEW, or drop and recreate the view with CREATE VIEW. If the view has been renamed (e.g., via sp_rename) or ownership has been transferred to a different schema, the script you get back will reflect the original CREATE/ALTER VIEW statement: it will not reflect the objects current name.
Some tools truncate the output. For example, the MS-SQL command line tool sqlcmd.exe truncates the data at 255 chars. You can pass the parameter -y N to get the result with N chars.
Microsoft listed the following methods for getting the a View definition: http://technet.microsoft.com/en-us/library/ms175067.aspx
USE AdventureWorks2012;
GO
SELECT definition, uses_ansi_nulls, uses_quoted_identifier, is_schema_bound
FROM sys.sql_modules
WHERE object_id = OBJECT_ID('HumanResources.vEmployee');
GO
USE AdventureWorks2012;
GO
SELECT OBJECT_DEFINITION (OBJECT_ID('HumanResources.vEmployee'))
AS ObjectDefinition;
GO
EXEC sp_helptext 'HumanResources.vEmployee';
For users of SQL 2000, the actual command that will provide this information is:
select c.text
from sysobjects o
join syscomments c on c.id = o.id
where o.name = '<view_name_here>'
and o.type = 'V'
SELECT object_definition (OBJECT_ID(N'dbo.vEmployee'))
You can get table/view details through below query.
For table :sp_help table_name
For View :sp_help view_name
SELECT definition, uses_ansi_nulls, uses_quoted_identifier, is_schema_bound
FROM sys.sql_modules
WHERE object_id = OBJECT_ID('your View Name');
This example:Views Collection, CommandText Property Example (VB)
Shows how to use ADOX to maintain VIEWS by changing COMMAND related to VIEW.
But instead using it like this:
Set cmd = cat.Views("AllCustomers").Command
' Update the CommandText of the command.
cmd.CommandText = _
"Select CustomerId, CompanyName, ContactName From Customers"
just try to use this way:
Set CommandText = cat.Views("AllCustomers").Command.CommandText

Can DTS Test for Presence of MS-Access Table

I have an Access database in which I drop the table and then create the table afresh. However, I need to be able to test for the table in case the table gets dropped but not created (i.e. when someone stops the DTS package just after it starts -roll-eyes- ). If I were doing this in the SQL database I would just do:
IF (EXISTS (SELECT * FROM sysobjects WHERE name = 'Table-Name-to-look-for'))
BEGIN
drop table 'Table-Name-to-look-for'
END
But how do I do that for an Access database?
Optional answer: is there a way to have the DTS package ignore the error and just go to the next step rather than checking to see if it exists?
SQL Server 2000
I'm not sure whether you can query the system objects table in an Access database from a DTS package.
If that doesn't work, why not just try doing a SELECT * from the Access table in question and then catch the error if it fails?
Try the same T-SQL, but in MS ACCESS the sys objects table is called:
MSysObjects.
Try this:
SELECT * FROM MSysObjects WHERE Name = 'your_table';
and see if it works from there.
You can take a look at these tables if you go to Tools -> Options -> View (a tab) -> and check Hidden Objects, System Objects. So you can see both. If you open the table, you should see your table names, queries, etc. Do not change this manually or the DB could panic :)
Martin.
P.D.: Your If Exists should also check of object type:
IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id(N'[dbo].[Your_Table_Name]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
Microsoft Access has a system table called MSysObjects that contains a list of all database objects, including tables. Table objects have Type 1, 4 and 6.
It is important to reference the type:
... Where Name='TableName' And Type In (1,4,6)
Otherwise, what is returned could be a some object other than a table.

Resources