tags:

views:

162

answers:

5

Hello

I'm trying to print out Tables from the DB that have the EntityId column equals to DataclassId column here is the code

    public void getRootTables_checkSP()
    {
        string connect = "Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes";
        SqlDataReader rootTables_List = null;
        SqlConnection conn = new SqlConnection(connect);
        conn.Open();

        SqlCommand s_cmd = new SqlCommand("SELECT * FROM sys.Tables WHERE EntityId = DataclassId", conn);
        rootTables_List = s_cmd.ExecuteReader();

        while (rootTables_List.Read())
        {
            string test = rootTables_List[0].ToString();
            Console.WriteLine("ROOT TABLES ARE {0}", test);
        }
        rootTables_List.Close();
        conn.Close();
    }

but it keeps saying that these columns are invalid though when I printed out all the columns in the DB "syscolumns" they were there...

Can anyone tell me why I'm getting such an error?

EDIT

What I really want is to query the db TacOps_4_0_0_4_test not the system. I just realized that

EDIT 2

Here is an example of the Tables in my DB

Table_1
ID  Sequence    Type    Heigh  Weight   EntityId    DataclassId
0   1           s       1.4     2.5     42-2c-Qi    42-2c-Qi
1   2           s       2.4     2.5     zh-km-xd    zh-km-xd
2   3           s       3.4     2.5     8n-tr-l7    8n-tr-l7

Table_2
ID  Data    Person    EntityId    DataclassId
0   1        Dave     58-zj-4o    41-2c-Q7
1   2        Sara     99-op-t6    oy-7j-mf
2   3        Silve    75-qy-47    2d-74-ds

Table_3
ID  Name    Genre   EntityId    DataclassId
0   LR      Ac      78-jd-o9    78-jd-o9
1   OI      Dr      4t-jb-qj    4t-jb-qj
2   DH      Do      7j-3e-ol    7j-3e-ol

The output should be

Table_1
Table_3
+6  A: 

EntityId and DataclassId are indeed no columns that exists in the sys.tables.

You're selecting data from sys.tables, there's no notion of syscolumns in your query, so i do not know why you're mentionning 'syscolumns' in your explanation ?

Frederik Gheysels
+1 - neither of those columns exist in sys.tables (or syscolumns/sys.columns)
AdaTheDev
I tried "syscolumns" just to make sure that the columns do exist. But when I do the query where EntityId = DataclassId it says "Invalid column name"
Reda
Which is logical ... those columns do not exist in sys.tables.
Frederik Gheysels
They don't exists in syscolumns either, so i don't know from where you're getting those ...
Frederik Gheysels
oh I get it! Sorry. I wanna query the columns in my connect string db I thought sys.tables gets me the tables for it
Reda
they are in every table in the TacOps_4_0_0_4_test db
Reda
A: 

Well, if you do a sp_help 'sys.Tables' in SQL Management Studio you'll see that, indeed, those columns are not part of sys.Tables...

Edgar Sánchez
+3  A: 

I think I may understand what you're trying now based on your comment to Frederik's answer

I tried "syscolumns" just to make sure that the columns do exist. But when I do the query where EntityId = DataclassId it says "Invalid column name

It sounds like EntityId and Dataclassid are columns in a table (or tables) that you have in your database and you want to find the rows from those tables that contain the same value in both those columns??

If that's the case, you are querying sys.Tables incorrectly - you'd need to query the specific tables directly i.e.

SELECT * FROM Table1 WHERE EntityId = DataClassId

Can you clarify?

Edit: You can find all the tables that contain both those columns using this:

SELECT t.name
FROM sys.tables t
WHERE EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='EntityId')
    AND EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='DataClassId')

From this, you could either iterate round each table and run the query to find rows that match on EntityId/DataClassId values - could insert into a temp table and return 1 resultset at the end.

OR, you could create a view to UNION all the tables together and then query that view (would need to update the view each time you added a new table).

OR, you could do some dynamic SQL generation based on the above to generate a SELECT statement on-the-fly to UNION all the tables together.

Update: Here's a generic way to do it in pure TSQL - this way means if new tables are added it will automatically include them:

DECLARE @SQL VARCHAR(MAX)

SELECT @SQL = COALESCE(@SQL + CHAR(10) + 'UNION ALL' + CHAR(10), '') 
    + 'SELECT ''' + REPLACE(QUOTENAME(t.Name), '''', '''''') + ''' AS TableName, COUNT(*) AS RowsMatched FROM ' + QUOTENAME(t.name) 
    + ' WHERE EntityId = DataClassId'
FROM sys.tables t
WHERE EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='EntityId')
    AND EXISTS(SELECT * FROM sys.columns c WHERE c.object_id = t.object_id AND c.name='DataClassId')

SET @SQL = 'SELECT x.TableName, x.RowsMatched FROM (' + @SQL + ') x WHERE x.RowsMatched > 0 ORDER BY x.TableName'
EXECUTE(@SQL)

If you don't need it to be dynamic, change the above EXECUTE to a PRINT to see the SQL it generates, and then create a view from it. You can then SELECT from that view.

Of course, you could either loop round each table 1 by 1 as you are trying.

AdaTheDev
true that's what I want but I want this for all tables not only one
Reda
@AdaTheDev: Actually I know all the tables have EntityId and DataclassId. Can't I directly query them for equal values?
Reda
@Reda - yep, if you know they all have them. If you don't want to define a view up front, but instead want to dynamically look at each table that exists at execution time, then you could scrap the WHERE clause on sys.tables to just return all tables
AdaTheDev
I don't want all tables I want all tables that have the same values under EntityId and DataclassId. Can you tell me how the condition would look like for this query (i.e instead of the last WHERE clause in your code)
Reda
@ AdaTheDev: Check my Answer. I tried what you first suggested but I didn't get the correct output
Reda
@AdaTheDev-Update: You mean I put this inside the first while loop?
Reda
I actually no nothing of the TSQL. Is there another method for this? Because I still need to do some test on the root tables after I get them
Reda
@Reda - I mean, only have 1 SqlCommand + SqlDataReader. Execute something like what I've put in my update, which will return in one call a list of all the tables with the corresponding row count. So you wouldn't need nested loops as you get all the data in one go.
AdaTheDev
@AdaTheDev: Thx it works :D finally I can move on. But do you know how can I skip the Null tables? I noticed that it also takes the tables with null values. Can you help me out with that?
Reda
@Reda - Pls see I've updated the SQL (added in "REPLACE") to guard against any single quotes in table names (unlikely but possible). The [] are added by the QUOTENAME function call that wraps "t.Name" - removing that function call would remove the square brackets.
AdaTheDev
@AdaTheDev: Actually I went more thoroughly in the list and discovered that the query doesn't work as it suppose to. There were some tables retrieved that have different EntityId and DataclassId... Is there other way than TSQL? I need to know how I'm querying
Reda
@Reda - You really need to give an exact, specific example (example tables with example rows) and clarify what you want to be returned. Otherwise I'm just trying to work it out in the dark
AdaTheDev
ok I'll add some in my original post soon. your help is greatly appreciated
Reda
@Reda - please see I've updated the SQL in the "Update" section of my answer - it will now only return records for the tables that do having matching rows on those 2 fields. Tables with no matches, will not be returned.
AdaTheDev
@AdaTheDev: I posted another similar post on this link (http://stackoverflow.com/questions/3785058/query-to-select-tables-with-similar-column-values)
Reda
@AdaTheDev: I went through all the generated list and compared it with the DB Tables, here is what I came up with: Your query selects exactly the opposite of what I needed (i.e. Tables with different EntityId/DataclassId columns. I fixed that easily by modifying the WHERE clause. I also noticed that the generated list also contains empty tables (with Null in all their rows) how can I filter these?
Reda
@Reda - I've updated the final WHERE clause, just before the execute (see updated SQL). Basically: "WHERE x.RowsMatched > 0" instead of "WHERE x.RowsMatched = 0". Quick test with 4 tables, 1 with matching rows in, 1 without matching rows, 1 with no rows in, and 1 with rows that only have NULLs in each of those columns - that behaves as expected, only returning the 1 table that does have matches in.
AdaTheDev
Yes that's it :D My struggle (and yours) is finally over. Thx a lot AdaTheDev
Reda
No problem. Glad we got there in the end!
AdaTheDev
+1  A: 

Based on all the comments, i think what you might be trying to find is ALL tables in your database that have both EntityID and DataClassID columns.

I know...its a pretty WILD guess but dont blame me for trying!! :-)

If my shot in the pretty awesome darkness that is your question is correct, try this out:

SELECT tabs.name 
FROM sys.tables tabs INNER JOIN sys.columns cols
ON tabs.object_id = cols.object_id
AND cols.name IN ('EntityId', 'DataClassId')
InSane
almost! I wanna find only tables that have the column EntityId equal to DataclassId
Reda
@Reda - what exactly do you mean by "column EntityId equal to DataclassId" ? Are columns equal if they have the same datatypes? Are columns equal if they have similar datatypes eg an int and a smallint are similar? What is your criteria for equating columns?
InSane
@In Sane: I mean they have the same values (i.e. Col_1 has 3 and Col_2 has 3 as well)
Reda
@Reda - i dont think that there is any way to do that using these sys views that we are talking about. In order to match data, you dont have a choice but to query the actual tables that have the data.Eg : If there is a table X with EntityId and DataclassId columns. Now, table X may have some rows that may have entityId and DataclassId same and some rows different. The only way you can know is by doing a Select count(*) from X where EntityId = DataClassId.
InSane
In my DB if a table has one row with the same EntityId and DataclassId then all rows will have the same. As for the query you wrote I want X to stand for all the tables in my DB. How do I iterate through them using c# code? and btw it's not a must to use sys views I was just trying.. any other solution is fine by me
Reda
@In Sane: Check my answer!
Reda
A: 

So here is what I came up with after the helpful answers... but I still don't get the correct output. I'm pretty sure there is some major drastic logic error in my code so I hope you could help me out.

I commented the code so it will be easier to understand

    public void getRootTables_checkSP()
    {
        string connect = "Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes";
        //Query to Select all Tables that have  
        //EntityId and DataclassId columns in them
        string query =
            "SELECT tabs.name " +
            "FROM sys.tables tabs INNER JOIN sys.columns cols " +
            "ON tabs.object_id = cols.object_id " +
            "AND cols.name IN ('EntityId', 'DataclassId')";
        int i = 0;  //Count for all Tables with EntityId and DataclassId
        int j = 0;  //Count for Root Tables (share same EntityId and DataclassId value)
        SqlDataReader tables_list = null;
        SqlDataReader rootTables_list = null;
        SqlConnection conn = new SqlConnection(connect);
        SqlConnection conn2 = new SqlConnection(connect);
        try
        {
            //Write all table that have EntityId and
            //DataclassId cols into tables_list
            conn.Open();
            SqlCommand cmd_1 = new SqlCommand(query, conn);
            tables_list = cmd_1.ExecuteReader();
            //Loop through the tables_list
            while (tables_list.Read())
            {
                //Query to select Root Tables.
                //EntityId and DataclassId values are identical in Root Tables
                string rootQ =
                    "SELECT count(*) " +
                    "FROM " + tables_list[0] + " " +
                    "WHERE EntityId = DataclassId";
                try
                {
                    //Write Root Tables into rootTables_list
                    conn2.Open();
                    SqlCommand cmd_2 = new SqlCommand(rootQ, conn2);
                    rootTables_list = cmd_2.ExecuteReader();

                    //Loop through the rootTables_list and print out the values
                    while (rootTables_list.Read())
                    {
                        Console.WriteLine(rootTables_list[0]);
                        j++;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex);
                }
                finally
                {
                    Console.WriteLine();
                    Console.WriteLine("{0} j-Count ", j);
                    Console.WriteLine();
                    conn2.Close();
                }
                i++;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Error: " + e);
        }
        finally
        {
            Console.WriteLine();
            Console.WriteLine("{0} i-Count ", i);
            Console.WriteLine();
            conn.Close();
        }
Reda
Can you give a formatted example of the exact output you want to see?
AdaTheDev
I want the output to be the name of the tables that have EntityId and DataclassId column values as identical values (in my case I call them the Root Tables).
Reda
See my latest update in my answer
AdaTheDev