I'm using SQL Server 2000, and given a a set of data (with unique ID's), I want to figure out the diffs with rows in the database, matching on the unique IDs. I'm also trying to keep it as flexible as possible.
I can use C#/VB in the front end to take the parameters, or even return things. Maybe passing in XML and getting XML in return?
For example, I want a function that calls:
// returns the columns that are different
func( A, B, C ) {
}
Any ideas?
There's a cool trick you can use with UNION:
SELECT MAX(tbl) AS TABLE_NAME, unique_key
FROM (
SELECT 'table1' AS tbl, unique_key
FROM table1
UNION ALL
SELECT 'table2' AS tbl, unique_key
FROM table2
) AS X GROUP BY unique_key
HAVING COUNT(*) = 1
This will show where one side or the other has rows which the other doesn't have.
This can be expanded to do more, obviously.
Alternatively, you can do an INNER JOIN (matches on keys where data is different), LEFT JOIN (key missing on one side) and RIGHT JOIN (key missing on the other) and UNION them all together.
I actually have a utility SP (it uses one or the other method depending on what options you need) which will compare any two tables and has options for setting which columns are considered the part of keys, which columns to ignore, restrict each side to a subset, etc. It even has an option to write the differences to a table.
I'd go with an existing "data diff" tool like
Red-Gate SQL Data Compare
ApexSQL Data Diff
Marc
Yeah agree with Marc, a specialized tool works best, something like Volpet Table Diff for SQL Server
Related
Today I encountered problem that causes difficulty for me to solve it.
In application I want to display records in aphabetical order thus in SQL statement I'am using ORDER BY, But it looks like CAPITAL letters are before lowercase letters so record starting with Z is before a.
This is example of my sql statement
SELECT * FROM myTable WHERE id= 5 ORDER BY name
Do you have any ideas ? Can I sort data in DataTable object after retreiving it from database ? or can it be accomplished by more complex sql statement?
Any ideas will be appreciated
You can modify your SQL query in such a way that all capitals are transformed to lower before ordering
SELECT * FROM myTable WHERE id = 5 ORDER BY LOWER(name)
The rules for comparing text values is the collation; there are many many collations available in SQL Server, and most have both case-sensitive and case-insensitive options.
If you don't want to change the collation (in particular, if this applies only to specific cases), you can also use functions like LOWER / UPPER, but this cannot make efficient use of indexes. A hybrid approach is to store redundant information: store the original data in one column, and the standardized data (perhaps all lower-case-invariant) in a second column. Then you can index the two separately (as you need), and operate on either the original or standardized data. You would normally only display the original data, though. Persisted+calculated+indexed columns might work well here, as then it is impossible to get inconsistent data (the server is in charge of the calculated column).
Try
SELECT * FROM myTable WHERE id= 5 ORDER BY LOWER(name)
OR
SELECT * FROM myTable WHERE id= 5 ORDER BY LCASE(name)
depending on which database you are using
You can perform ordering by providing case in SQL. Just do this:
SELECT * FROM myTable WHERE id= 5 ORDER BY UPPER(name)
OR
SELECT * FROM myTable WHERE id= 5 ORDER BY UCASE(name)
Ordering will be done on upper case name while you result will be same as present in table.
Try this...
SELECT * FROM myTable WHERE id= 5 ORDER BY name COLLATE Latin1_General_100_CI_AS
I am working on a C# application that uses a database. I need to join two tables together, but they are linked strangely. One table has letters identifying the data like A, B, C, etc. and the other has string values identifying the type like "small" or "large"
I need to join the tables so that the values in the first table's column with the code 'a' link to the other table's column with the value of "small" and the values that are 'b' or 'd' link to the other table's value of "large"
What is the best way to do this using standard SQL. Is there some way I can have extra conditionals in the join statement or is it best to do something like this in a where clause?
Thanks,
-Jake
The easiest method to handle this would be to have an intermediate table that maps the the values. You can then add this table to your statement and use it join the main tables together.
Make a case statement to map a to 'small' and b,c,d... to 'Large' in your first table,with the new field join the tables
Make an intermediate table or query.
SELECT *
FROM (
SELECT CASE col WHEN 'A' THEN 'small'
WHEN 'B' THEN 'large'
WHEN 'D' THEN 'large'
ELSE NULL
END AS col
FROM one
) x
JOIN two t
ON x.col = t.col
http://sqlfiddle.com/#!6/45eb0/1
Based on your description, I think you can use Common table expression , to select those values you need , as well as the column which has A,B,C values. Then use CTE to join your second table. it will looks like the following.
;WITH A_CTE (columns)
AS
(
select column1,columnb, CASE A_B_C_COLUMN WHEN 'A' THEN 'LARGE' WHEN 'B' THEN 'SMALL' WHEN 'C' THEN 'TINY' END AS ColumnC
)
select * from A_CTE JOIN TABLEB ON A_CTE.ColumnC = TABLEB.ConditionColumn
if you can provide more detail, happy to write the SQL Statement for you.
I have a task to construct a dynamic query (or algorithm) based on existing query with user choosed fields. Let me explain:
Lets say I have a function
ConstructQuery(string inputQuery, string[] mandatoryTables, string[] userFields) with 2 input parameters:
inputQuery: string query with many fields and tables, joins and where conditions
mandatoryTables: a list of mandatory tables
userFields: a list of fields that user choose in some web or desktop app
Function would have to return optimized query with tables and joins that are only needed for query to succeed.
inputQuery is for example constructed like this:
SELECT
Table1.SomeFieldA,
Table2.SomeFieldB,
Table2.SomeFieldC,
Table3.SomeFieldD
FROM Table1
JOIN Table2 ON Table1.Code = Table2.Code
JOIN Table3 ON Table2.Code = Table3.Code
WHERE Table1.SomeConditionField = "xyz"
userFields are: SomeFieldB, SomeFieldC
mandatoryTables: Table1
So the expected query is:
SELECT
Table2.SomeFieldB,
Table2.SomeFieldC
FROM Table1
JOIN Table2 ON Table1.Code = Table2.Code
WHERE Table1.SomeConditionField = "xyz"
My question is: is there a tool of some sort for solving this kind of problems or how you guys would solve it? I'm thinking of binary trees…
Regards,
Jani
This is something called join removal. This is (very) hard. Just parsing the query is nontrivial, then You'd have to analyze semantics, consider what are the unique keys, what are foreeign keys to have a chance to remove some tables. In Your example: the algorithm would have to know that table3.code is unique, and a foreign key to table2.code, otherwise the queries are not equivalent.
It could be easier to generate the right query in the first place. This is what some ORMs do.
I am writing a table differ utility for checking differences between similar schema tables in access and sql server. all i want to know that what could be the fastest way of achieving it as i have a very large number of tables in both the databases.
i am comparing two tables lets say tableX in both access and sql with same schema and same column definitions and constraints and it has different rows and tuples in tables i want to identify that difference and extract that difference
Thanks
Steave
Unfortunately it sounds like you want very fine grain differencing between two disparate systems, which does not allow for a lot of efficiency.
If the tables are not too huge, your best bet might be to export to CSVs (make sure to order the results!) and run a diff command against them.
If all you need to check are field names and types, ADO may suit: http://www.w3schools.com/ado/met_conn_openschema.asp. You will not get an exact match between Access field types and SQL Server field types.
Create a linked server to your ms access database and use queries to diff your tables:
EXEC sp_addlinkedserver #server = 'DBName'
, #provider = 'Microsoft.Jet.OLEDB.4.0'
, #srvproduct = 'OLE DB Provider for Jet'
, #datasrc = 'C:\myaccessdb.mdb'
comparing 2 tables is easiest with a query like this
SELECT MIN(table_name), column1, column2, ...
FROM (
SELECT 'sql server table' , column1, column2, ...
FROM A
UNION ALL
SELECT 'msaccess table' , column1, column2, ...
FROM B) tmp
GROUP BY column1, column2, ...
HAVING COUNT(*) = 1
Another option is to rely on the tablediff.exe utility which comes with Sql Server. See more info on msdn
I am a PHP/MySQL developer, slowly venturing into the realm of C#/SQL Server and I am having a problem in C# when it comes to reading an SQL Server query that joins two tables.
Given the two tables:
TableA:
int:id
VARCHAR(50):name
int:b_id
TableB:
int:id
VARCHAR(50):name
And given the query
SELECT * FROM TableA,TableB WHERE TableA.b_id = TableB.id;
Now in C# I normally read query data in the following fashion:
SqlDataReader data_reader= sql_command.ExecuteReader();
data_reader["Field"];
Except in this case I need to differentiate from TableA's name column, and TableB's name column.
In PHP I would simply ask for the field "TableA.name" or "TableB.name" accordingly but when I try something like
data_reader["TableB.name"];
in C#, my code errors out.
How can fix this? And how can I read a query on multiple tables in C#?
The result set only sees the returned data/column names, not the underlying table. Change your query to something like
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
Then you can refer to the fields like this:
data_reader["Name_TA"];
To those posting that it is wrong to use "SELECT *", I strongly disagree with you. There are many real world cases where a SELECT * is necessary. Your absolute statements about its "wrong" use may be leading someone astray from what is a legitimate solution.
The problem here does not lie with the use of SELECT *, but with a constraint in ADO.NET.
As the OP points out, in PHP you can index a data row via the "TABLE.COLUMN" syntax, which is also how raw SQL handles column name conflicts:
SELECT table1.ID, table2.ID FROM table1, table;
Why DataReader is not implemented this way I do not know...
That said, a solution to be used could build your SQL statement dynamically by:
querying the schema of the tables you're selecting from
build your SELECT clause by iterating through the column names in the schema
In this way you could build a query like the following without having to know what columns currently exist in the schema for the tables you're selecting from
SELECT TableA.Name as Name_TA, TableB.Name as Name_TB from ...
You could try reading the values by index (a number) rather than by key.
name = data_reader[4];
You will have to experiment to see how the numbers correspond.
Welcome to the real world. In the real world, we don't use "SELECT *". Specify which columns you want, from which tables, and with which alias, if required.
Although it is better to use a column list to remove duplicate columns, if for any reason you want *****, then just use
rdr.item("duplicate_column_name")
This will return the first column value, since the inner join will have the same values in both identical columns, so this will accomplish the task.
Ideally, you should never have duplicate column names, across a database schema. So if you can rename your schema to not have conflicting names.
That rule is for this very situation. Once you've done your join, it is just a new recordset, and generally the table names do go with it.