I'm writing a script that analyses database tables and I'm having problems with fetching the default value of columns from SQL Server 2005.
The following works fine on SQL Server 2008, but when I run the same thing on SQL Server 2005, the result is an empty string, and I can't figure out why.
DECLARE #sDatabase VARCHAR(100);
DECLARE #sTable VARCHAR(100);
DECLARE #sColumn VARCHAR(100);
SET #sDatabase = 'SomeDatabase';
SET #sTable = 'tbl_something';
SET #sColumn = 'SomethingID';
SELECT
syscolumns.name AS column_name,
systypes.name column_type,
syscolumns.length AS column_length,
syscolumns.prec AS column_precision,
syscolumns.scale AS column_scale,
syscolumns.isnullable AS column_nullable,
syscomments.text AS column_default_value -- Should be default value!
FROM
sysobjects
INNER JOIN syscolumns ON sysobjects.id = syscolumns.id
INNER JOIN systypes ON syscolumns.xtype = systypes.xtype
LEFT OUTER JOIN syscomments ON syscomments.id = syscolumns.cdefault
WHERE sysobjects.xtype = 'U'
AND sysobjects.name = #sTable
AND systypes.name != 'sysname'
ORDER BY
sysobjects.name,
syscolumns.colid
Another version is as follows, but it's the same story; returns an empty string on SQL Server 2005, but the correct value on SQL Server 2008.
SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = #sDatabase
AND TABLE_NAME = #sTable
AND COLUMN_NAME = #sColumn
This is used for comparing certain changes between databases. Originally I thought that the problem was because SQL Server 2005 returned default values such as "((0))" while SQL Server 2008 was returning "(0)" for the same default value of the integer 0. That's what SQL Server Management Studio reports respectively. But upon further investigation, it turns out that the default values of SQL Server 2005 are simply not being displayed at all, so it is always recorded as a change when in fact there is none.
Any help deeply appreciated.
Thanks!
Have you tried the sys.default_constraints view?
This snippet finds the default for table TestTable column nr:
create table TestTable (nr float default 3.13)
select definition
from sys.default_constraints dc
join sys.columns c
on c.object_id = dc.parent_object_id
and c.column_id = dc.parent_column_id
where parent_object_id = object_id('TestTable')
and c.name = 'nr'
Related
I have really strange problem (or misunderstanding) of the string concatenation on Azure Sql. I used to build T-SQL code for EXEC like this:
DECLARE #tsql nvarchar(max)
SELECT #tsql = CONCAT(#tsql, Prop1, Prop2) FROM Table
PRINT #tsql
This works fine in SQL from 2012 to 2016. But in Azure SQL I have really strange behavior: only LAST row is in #tsql
Here is live T-SQL to clean up some tables:
DECLARE #deleteTsql nvarchar(max)
SET #deleteTsql = ''
-- just show all table
SELECT O.[name] FROM [sys].[objects] O
LEFT JOIN sys.schemas SCH on O.schema_id = SCH.schema_id
WHERE (SCH.[name] = 'dbo' AND [type] = 'U') or (SCH.[name] = 'data' and O.[name] = 'Objects')
ORDER BY O.create_date desc
-- build T-SQL to cleanup
SELECT #deleteTsql = CONCAT(#deleteTsql, 'PRINT ''Deleting data from ', O.[name], '''', CHAR(10), CHAR(13), 'DELETE FROM [', SCH.[name], '].', '[', O.[name],']', CHAR(10), CHAR(13)) FROM [sys].[objects] O
LEFT JOIN [sys].[schemas] SCH on O.[schema_id] = SCH.[schema_id]
WHERE (SCH.[name] = 'dbo' AND [type] = 'U') or (SCH.[name] = 'data' and O.[name] = 'Objects')
ORDER BY O.create_date desc
PRINT #deleteTsql
This works fine in SQL 2016. For instance I have tables data.Objects, dbo.Table1 and dbo.Table2. Then following will be printed:
(3 rows affected)
PRINT 'Deleting data from Objects'
DELETE FROM [data].[Objects]
PRINT 'Deleting data from Table1'
DELETE FROM [dbo].[Table1]
PRINT 'Deleting data from Table2'
DELETE FROM [dbo].[Table2]
But if I do the same on Azure SQL (v12) database with same tables then I got this:
(3 rows affected)
PRINT 'Deleting data from Table2'
DELETE FROM [dbo].[Table2]
So only last record is in #deleteTsql.
Why?????
The result for aggregate concatenation (with the SELECT #x=#x+... syntax) is undefined. See KB 287515 and this answer. Using CONCAT does not change that. As Panagiotis Kanavos suggested, you should use STRING_AGG or GROUP_CONCAT.
And one more thing: in my databases, I get the results from a single row using your query, even in SQL Server 2016 or SQL Server 2017. So it's not an Azure thing, it's just depending on the execution plan (if it is using a nested loops join, you get all the rows; if it is using a merge join, you get a single row). That may be dependant on the number of rows in the system tables, the CPU count, the updated statistics, etc.
I have a query in a SQL Server database that gets stored procedures parameters like this:
SELECT
parameter.name,
types.name,
types.is_nullable
FROM
sys.parameters AS parameter
INNER JOIN
sys.procedures AS procedures ON parameter.object_id = procedures.object_id
INNER JOIN
sys.types AS types ON parameter.system_type_id = types.system_type_id
AND parameter.user_type_id = types.user_type_id
WHERE
procedures.name = 'UsernameSP'
This returns a result set:
name name is_nullable
--------------------------------------
#Username nvarchar 1
#CreateDate datetime 1
I need this query for an Oracle database. How can I run this query in Oracle?
select argument_name,position, data_type
from user_arguments
where object_name = <your procedure>
order by position
That assumed you are logged in to the current schema where the procedure resides. I don't think oracle has an equivalent of "is_nullable"
When I'm trying to update some data like
if Exists(select * from sys.columns where Name = N'Enabled'
and Object_ID = Object_ID(N'SLBPool'))
begin
update SLBPool set SLBPool.Enabled=1
End
GO
it shows error "Invalid column name 'Enabled'" in SQL 2012,however ,not happened with 2008 R2
how come ?
The only way this should work on any version of SQL Server (certainly as far back as 2000, IIRC) is if you prevent the statement from being compiled until after you've evaluated the if condition - which would indicate dynamic SQL:
if Exists(select * from sys.columns where Name = N'Enabled'
and Object_ID = Object_ID(N'SLBPool'))
begin
exec sp_executesql 'update SLBPool set SLBPool.Enabled=1'
End
GO
Possibly this is because of collation prefs of server instance, check if this works, or produces some other error:
IF EXISTS(SELECT * FROM sys.columns WHERE name = N'Enabled'
AND object_id = OBJECT_ID(N'SLBPool'))
BEGIN
UPDATE SLBPool SET SLBPool.Enabled = 1
END
GO
HI I need to export Database Schema from SQL Server management studio express 2005 into MSExcel? generate script is giving me the script. but i need to have Excel file contains database schema. how do i do with SQL server management studio express 2005?
What you could do is use this script to get all the table data, and copy-paste the results to an Excel file:
SELECT o.name AS TableName
, c.name AS ColumnName
, t.name AS DataType
, c.Max_Length
, c.Precision
, c.Scale
FROM sys.objects AS o
INNER JOIN sys.columns AS c ON o.object_id = c.object_id
INNER JOIN sys.types AS t ON c.user_type_id = t.user_type_id
WHERE type = 'U'
ORDER BY
o.name
, c.name
Unfortunately I am not too familiar with SQL server 2005
How about Import and Export Wizard?
The wizard should have the option to select destination type
I am using Microsoft SQL Server 2008. I have a stored procedure. Is there a simple query I can execute that will give me the parameter names?
I have found this Link but it is not for Microsoft SQL Server 2008.
To get names only you can use this query:
SELECT name
FROM sys.parameters
WHERE object_id = OBJECT_ID('YourProcedureName')
To get more detailed info (name, type and length of parameter):
SELECT p.name AS ParameterName, t.name AS ParameterType, p.max_length AS ParameterLength
FROM sys.parameters AS p
JOIN sys.types AS t ON t.user_type_id = p.user_type_id
WHERE object_id = OBJECT_ID('YourProcedureName')
On top of what Marek stated, you can also retrieve them programatically using the DeriveParameters method in the .NET library: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommandbuilder.deriveparameters.aspx
Check out my blog on database files and objects. http://craftydba.com/?p=2901
I have a stored procedure called SP_STORE_PRIMES in my sample [MATH] database.
One way is to use the sys.parameters table. This can be optionally joined to types. Below is joined to sys.objects.
-- Parameters to SP & FN
select o.name, p.* from sys.parameters p join sys.objects o
on p.object_id = o.object_id where is_ms_shipped = 0
go
A older system stored procedure is sp_sproc_columns.
-- Older system stored proc - show all parameters to one
sp_sproc_columns #procedure_name = 'SP_STORE_PRIMES'
go
Both ways will get you where you want to go.