Can anyone tell me why the generated SQL does not contain a 2nd INNER JOIN? It seems to have been replaced with a NULL check in the WHERE clause? I'm not clear on why the 2nd INNER JOIN is not in the generated SQL.
C# code:
var cycleList = from o in entities.Orders
join c in entities.Cycles on o.Id equals c.OrderId
join calendar in entities.Calendars on c.CalendarId equals calendar.Id
where o.UnitId == unitId && o.CompanyId == companyId
select c.Id;
Generated SQL:
SELECT
[Extent2].[Id] AS [Id]
FROM [dbo].[Orders] AS [Extent1]
INNER JOIN [dbo].[Cycles] AS [Extent2] ON [Extent1].[Id] = [Extent2].[OrderId]
WHERE ([Extent2].[CalendarId] IS NOT NULL) AND ( CAST( [Extent1].[UnitId] AS int) = #p__linq__0) AND ( CAST( [Extent1].[CompanyId] AS int) = #p__linq__1)
It looks like the query generator is optimizing your query.
Since you are not selecting (or using in your where clause) any fields from the Calendars table in your query, only one join is done between the Orders table and the Cycles table. It's likely faster to check for the non-NULL foreign key than it is to join on a table from which no fields will be used.
I'm looking at creating a basic ORM (purely for fun), and was wondering, is there a way to return the list of tables in a database and also the fields for every table?
Using this, I want to be able to loop through the result set (in C#) and then say for each table in the result set, do this (e.g. use reflection to make a class that will do or contain xyz).
Further to this, what are some good online blogs for SQL Server? I know this question is really about using system SPs and databases in Sql Server, and I am ok with general queries, so I'm interested in some blogs which cover this sort of functionality.
Thanks
Is this what you are looking for:
Using OBJECT CATALOG VIEWS
SELECT T.name AS Table_Name ,
C.name AS Column_Name ,
P.name AS Data_Type ,
C.max_length AS Size ,
CAST(P.precision AS VARCHAR) + '/' + CAST(P.scale AS VARCHAR) AS Precision_Scale
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
WHERE T.type_desc = 'USER_TABLE';
Using INFORMATION SCHEMA VIEWS
SELECT TABLE_SCHEMA ,
TABLE_NAME ,
COLUMN_NAME ,
ORDINAL_POSITION ,
COLUMN_DEFAULT ,
DATA_TYPE ,
CHARACTER_MAXIMUM_LENGTH ,
NUMERIC_PRECISION ,
NUMERIC_PRECISION_RADIX ,
NUMERIC_SCALE ,
DATETIME_PRECISION
FROM INFORMATION_SCHEMA.COLUMNS;
Reference : My Blog - http://dbalink.wordpress.com/2008/10/24/querying-the-object-catalog-and-information-schema-views/
Tables ::
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
columns ::
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
or
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='your_table_name'
Get list of all the tables and the fields in database:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName'
Get list of all the fields in table:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName' And TABLE_NAME Like 'TableName'
I tested a few solutions an found that
Select *
From INFORMATION_SCHEMA.COLUMNS
gives you the column info for your CURRENT/default database.
Select *
From <DBNAME>.INFORMATION_SCHEMA.COLUMNS
, without the < and >, gives you the column info for the database DBNAME.
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
Your other inbuilt friend here is the system sproc SP_HELP.
sample usage ::
sp_help <MyTableName>
It returns a lot more info than you will really need, but at least 90% of your possible requirements will be catered for.
Just throwing this out there - easy to now copy/paste into a word or google doc:
PRINT '<html><body>'
SET NOCOUNT ON
DECLARE #tableName VARCHAR(30)
DECLARE tableCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT T.name AS TableName
FROM sys.objects AS T
WHERE T.type_desc = 'USER_TABLE'
ORDER BY T.name
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO #tableName
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT '<h2>' + #tableName + '</h2>'
PRINT '<pre>'
SELECT LEFT(C.name, 30) AS ColumnName,
LEFT(ISC.DATA_TYPE, 10) AS DataType,
C.max_length AS Size,
CAST(P.precision AS VARCHAR(4)) + '/' + CAST(P.scale AS VARCHAR(4)) AS PrecScale,
CASE WHEN C.is_nullable = 1 THEN 'Null' ELSE 'No Null' END AS [Nullable],
LEFT(ISNULL(ISC.COLUMN_DEFAULT, ' '), 5) AS [Default],
CASE WHEN C.is_identity = 1 THEN 'Identity' ELSE '' END AS [Identity]
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
JOIN INFORMATION_SCHEMA.COLUMNS AS ISC ON T.name = ISC.TABLE_NAME AND C.name = ISC.COLUMN_NAME
WHERE T.type_desc = 'USER_TABLE'
AND T.name = #tableName
ORDER BY T.name, ISC.ORDINAL_POSITION
PRINT '</pre>'
FETCH NEXT FROM tableCursor INTO #tableName
END
CLOSE tableCursor
DEALLOCATE tableCursor
SET NOCOUNT OFF
PRINT '</body></html>'
SELECT * FROM INFORMATION_SCHEMA.COLUMNS for get all
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS for get all table name.
Try it on sqlserver,
This will get you all the user created tables:
select * from sysobjects where xtype='U'
To get the cols:
Select * from Information_Schema.Columns Where Table_Name = 'Insert Table Name Here'
Also, I find http://www.sqlservercentral.com/ to be a pretty good db resource.
This will return the database name, table name, column name and the datatype of the column specified by a database parameter:
declare #database nvarchar(25)
set #database = ''
SELECT cu.table_catalog,cu.VIEW_SCHEMA, cu.VIEW_NAME, cu.TABLE_NAME,
cu.COLUMN_NAME,c.DATA_TYPE,c.character_maximum_length
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE as cu
JOIN INFORMATION_SCHEMA.COLUMNS as c
on cu.TABLE_SCHEMA = c.TABLE_SCHEMA and c.TABLE_CATALOG =
cu.TABLE_CATALOG
and c.TABLE_NAME = cu.TABLE_NAME
and c.COLUMN_NAME = cu.COLUMN_NAME
where cu.TABLE_CATALOG = #database
order by cu.view_name,c.COLUMN_NAME
For MYSQL:
Select *
From INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = "<DatabaseName>"
I found an easy way to fetch the details of Tables and columns of a particular DB using SQL developer.
Select *FROM USER_TAB_COLUMNS
in a Microsoft SQL Server you can use this:
declare #sql2 nvarchar(2000)
set #sql2 ='
use ?
if ( db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'') )
begin
select
db_name() as db,
SS.name as schemaname,
SO.name tablename,
SC.name columnname,
ST.name type,
case when ST.name in (''nvarchar'', ''nchar'')
then convert(varchar(10), ( SC.max_length / 2 ))
when ST.name in (''char'', ''varchar'')
then convert(varchar(10), SC.max_length)
else null
end as length,
case when SC.is_nullable = 0 then ''No'' when SC.is_nullable = 1 then ''Yes'' else null end as nullable,
isnull(SC.column_id,0) as col_number
from sys.objects SO
join sys.schemas SS
on SS.schema_id = SO.schema_id
join sys.columns SC
on SO.object_id = SC.object_id
left join sys.types ST
on SC.user_type_id = ST.user_type_id and SC.system_type_id = ST.system_type_id
where SO.is_ms_shipped = 0
end
'
exec sp_msforeachdb #command1 = #sql2
this shows you all tables and columns ( and their definition ) from all userdefined databases.
Need to populate a dataset with all the tables in the database and each datatable must have the following column
TableName
ColumnName
IsNullable,
DataType
MaxLength
IsprimaryKey
IsForeignKey
I have done the following but this done not give me the primarykeys and foreignkeys
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.TABLE_SCHEMA='dbo'
ORDER BY C.TABLE_NAME
Tried to add a joint but I get wrong result
SELECT C.TABLE_SCHEMA,
C.TABLE_NAME,
C.COLUMN_NAME,
C.IS_NULLABLE,
C.DATA_TYPE,
C.CHARACTER_MAXIMUM_LENGTH,
TC.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
ON c.TABLE_NAME=TC.TABLE_NAME
WHERE C.TABLE_SCHEMA='dbo'
ORDER BY C.TABLE_NAME
How do I return all the info above about a table including if's a primary of foreignkey?
Thanks alot
If I got you correct then :
1.You need do LEFT join INFORMATION_SCHEMA.TABLE_CONSTRAINTS
2.Put the case
Try the below Query and let me know if i am correct?
SELECT
Distinct
C.TABLE_SCHEMA,
C.TABLE_NAME,
C.COLUMN_NAME,
C.IS_NULLABLE,
C.DATA_TYPE,
C.CHARACTER_MAXIMUM_LENGTH,
CASE WHEN TC.CONSTRAINT_TYPE='PRIMARY KEY' THEN 'Yes' Else 'No' end as ISprimaryKey,
CASE WHEN TC.CONSTRAINT_TYPE='FOREIGN KEY' THEN 'Yes' Else 'No' end as IsForeignKey
FROM INFORMATION_SCHEMA.COLUMNS C with(nolock)
LEFT join INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC with(nolock) on c.TABLE_NAME=TC.TABLE_NAME
WHERE C.TABLE_SCHEMA='dbo'
ORDER BY C.TABLE_NAME
I am currently trying to retrieve the table names and primary key of each table by calling the following SQL in C#. This is what I've tried so far:
SELECT t.TABLE_NAME As 'Table Name',
Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES t
left outer join INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
on t.TABLE_NAME = Constraints.Table_name
and t.Table_Schema = Constraints.Table_Schema
left outer join INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS Keys
ON Constraints.TABLE_NAME = Keys.TABLE_NAME
and Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME
and Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY'
The problem is that I would like the result to just contain a "null" entry if a table does not have a primary key. While it is working, for some reason the result contains a duplicate of the "Salary" table as shown below. The Salary and Employees tables both have primary keys, and the "Test" table does not:
EDIT: I've tried this now, and it seems to work. Are there any disadvantages to doing so?
SELECT T.TABLE_NAME As 'Table Name'
, (
Select K1.COLUMN_NAME
From INFORMATION_SCHEMA.TABLE_CONSTRAINTS As C1
Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As K1
On C1.TABLE_SCHEMA = K1.TABLE_SCHEMA
And C1.TABLE_NAME = K1.TABLE_NAME
And C1.CONSTRAINT_NAME = K1.CONSTRAINT_NAME
Where C1.CONSTRAINT_TYPE = 'PRIMARY KEY'
And T.TABLE_SCHEMA = C1.TABLE_SCHEMA
And T.TABLE_NAME = C1.TABLE_NAME
)As PrimaryKeyColumns
FROM INFORMATION_SCHEMA.TABLES As T
Try replace this condition Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY' :
SELECT t.TABLE_NAME As 'Table Name',
Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES t
left outer join INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
on t.TABLE_NAME = Constraints.Table_name
and t.Table_Schema = Constraints.Table_Schema
and Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY'
left outer join INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS Keys
ON Constraints.TABLE_NAME = Keys.TABLE_NAME
and Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME
You should account for your PK having multiple columns. You can do this by changing to a subquery:
SELECT T.TABLE_NAME As 'Table Name'
, Stuff(
(
Select ', ' + K1.COLUMN_NAME
From INFORMATION_SCHEMA.TABLE_CONSTRAINTS As C1
Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As K1
On C1.TABLE_SCHEMA = K1.TABLE_SCHEMA
And C1.TABLE_NAME = K1.TABLE_NAME
And C1.CONSTRAINT_NAME = K1.CONSTRAINT_NAME
Where C1.CONSTRAINT_TYPE = 'PRIMARY KEY'
And T.TABLE_SCHEMA = C1.TABLE_SCHEMA
And T.TABLE_NAME = C1.TABLE_NAME
For Xml Path(''), type
).value('.', 'nvarchar(max)')
, 1, 2, '') As PrimaryKeyColumns
FROM INFORMATION_SCHEMA.TABLES As T
Btw, if you really want to use Joins to the TABLES view, you need to nest the joins. The problem is that you have two outer joins and the columns from the foreign keys are generating rows in your output. It should be noted that the downside to the following approach over the earlier mentioned subquery approach is that you will get multiple rows if a primary key consists of multiple columns. That said, you can nest joins in SQL Server so that it processes the inner, inner join first and then the outer join:
SELECT T.TABLE_NAME As 'Table Name'
, Keys.COLUMN_NAME AS 'Primary Key'
FROM INFORMATION_SCHEMA.TABLES As T
Left Join( INFORMATION_SCHEMA.TABLE_CONSTRAINTS Constraints
Join INFORMATION_SCHEMA.KEY_COLUMN_USAGE As Keys
On Constraints.TABLE_SCHEMA = Keys.TABLE_SCHEMA
And Constraints.TABLE_NAME = Keys.TABLE_NAME
And Constraints.CONSTRAINT_NAME = Keys.CONSTRAINT_NAME
And Constraints.CONSTRAINT_TYPE = 'PRIMARY KEY' )
On T.TABLE_SCHEMA = Constraints.TABLE_SCHEMA
And T.TABLE_NAME = Constraints.TABLE_NAME
In this query, the Inner Join between TABLE_CONSTRAINTS and KEY_COLUMN_USAGE is processed first and the results are combined in a Left Join to TABLES view.
I see you have already accepted your answer, but here's a pure C# answer in case someone is interested:
static void Main(string[] args)
{
Server server = new Server("serverName");
Database db = server.Databases["DatabaseName"];
string tableName = "TableName";
Table table = db.Tables[tableName];
if (table != null)
{
Console.WriteLine("Table: {0}", tableName);
if (table.Columns.Count > 0)
{
Console.WriteLine(" Primary Key Columns:");
foreach (Column column in table.Columns)
{
if (column.InPrimaryKey)
{
Console.WriteLine(string.Format(" {0}", column.Name));
}
}
}
else
{
Console.WriteLine(" No primary key.", tableName);
}
}
Console.WriteLine("Press ENTER to exit...");
Console.ReadLine();
}
You will need to add references to the Microsoft.SqlServer.Management.Sdk.Sfc and Microsoft.SqlServer.Smo assemblies and import the appropriate namespaces.
select
TABLE_SCHEMA,
TABLE_NAME
from
INFORMATION_SCHEMA.TABLES
where
objectproperty(object_id(table_name),'TableHasPrimaryKey')=0
ORDER BY
TABLE_NAME
As a result of this query I have a table:
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
Now I need to use the result of this table in the next query:
select PriceListItem.ProductExternalId, #id.Id, #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from [#id]
inner join [Product] on Product.ItemId = #name and Product.InstanceId = #id.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId
instead of '#id' I should use data from the table with name= id, and instead of '#name' I should use data from the table with name= name
Standard SQL way, works in most RDBMS
select PriceListItem.ProductExternalId, #id.Id, #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from
(
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
)
X
inner JOIN
[#id] ON X.id = #id.id --change here as needed
inner join [Product] on Product.ItemId = #name and Product.InstanceId = #id.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId*
Since you're on SQL 2K8 you can use a CTE:
-- You may need a ; before WITH as in ;WITH
WITH FirstQuery AS (
select i.id, o.[name] from Item i
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
)
select PriceListItem.ProductExternalId,
FQ.Id,
-- Neither of these are in your FirstQuery so you can not use them
-- #id.FriendlyName, #id.BriefWiki,
[PriceListItem].[ProductExternalDesc]
from FirstQuery FQ
inner join [Product] on Product.ItemId = FQ.name
and Product.InstanceId = FQ.ID
inner join [PriceListItem] on Product.ID = PriceListItem.ProductId;
From the queries alone it's tough to tell how you plan to JOIN them, but this will allow you to make use of the first query in the subsequent one.
Looks like you have some syntax errors in your second query - #id.id?
select i.id, o.[name] from Item i
into #temp_table
LEFT OUTER JOIN sys.objects o on o.[name]='I' + cast(i.id as nvarchar(20))
where o.name is not null
Now you can use #temp_table as you want :)