SQLite INNER JOIN with ATTACHed databases - vb.net

I have two SQLite databases with identical table structures that I need to query using VB.Net, but I can figure out pretty much any syntax. I am trying to figure out how to build the query string? This query works correctly:
sb = New StringBuilder("SELECT Master.Name, Master.ID, Master.StartDate, Master.Supervisor, Log.LogType, Log.LogComment FROM Master INNER JOIN Log ON Master.ID = Log.ID WHERE date(Log.LogDate) = '")
sb.Append(calendarDate.ToString("yyyy-MM-dd"))
sb.Append("' ORDER BY Master.Name;")
c = New SQLiteCommand(sb.ToString, _Conn)
Using dr As SQLiteDataReader = c.ExecuteReader
...
I can also "attach" the second database with the following:
sb = New StringBuilder("ATTACH DATABASE '")
sb.Append(outDBPath)
sb.Append("' AS db2;")
c = New SQLiteCommand(sb.ToString, _Conn)
c.ExecuteNonQuery()
c.Dispose()
My question is, what is the syntax to query both databases? Is this even possible? In the past I used a For... Next loop and just changed the connection from the first database to the second.

http://www.sqlite.org/lang_attach.html:
Tables in an attached database can be referred to using the syntax
database-name.table-name. If the name of the table is unique across
all attached databases and the main and temp databases, then the
database-name prefix is not required. If two or more tables in
different databases have the same name and the database-name prefix is
not used on a table reference, then the table chosen is the one in the
database that was least recently attached.
So you use db2.Master to refer to the Master table in the attached database.

Related

Looping in R through databases to get the table schema in sql and show the output in R

I'm new to both R and SQL. The program I'm writing is in R language, and it is supposed to get the table schema or table description of all the tables which are there in approx 34 databases; the name of databases starts with RM_%. I'm doing this using RODBC package in R language; I have taken the list of all the databases in list of R language using the following command :
listOfRMSDatabase <- sqlQuery(dbhandle, "SELECT name FROM master.dbo.sysdatabases where name like 'RM_%'")
And the command in sql to get the schema is
SELECT *
FROM database_name.INFORMATION_SCHEMA.COLUMNS
I'm thinking to do it loop in R, so that every time the new database would be give the result and can be saved and appended or shown separately , but I'm not sure how to do this in the loop, do I need to save the data in dataframe, can somebody advice and help me in the code. Thanks.

Using table variables in Oracle Stored Procedure

I have lots of experience with T-SQL (MS SQL Server).
There it is quite common to first select some set of records into a
table variable or say temp table t, and then work with this t
throughout the whole SP body using it just like a regular table
(for JOINS, sub-queries, etc.).
Now I am trying the same thing in Oracle but it's a pain.
I get errors all the way and it keeps saying
that it does not recognize my table (i.e. my table variable).
Error(28,7): PL/SQL: SQL Statement ignored
Error(30,28): PL/SQL: ORA-00942: table or view does not exist
I start thinking what at all is possible to do with this
table variable and what not (in the SP body) ?
I have this declaration:
TYPE V_CAMPAIGN_TYPE IS TABLE OF V_CAMPAIGN%ROWTYPE;
tc V_CAMPAIGN_TYPE;
What on Earth can I do with this tc now in my SP?!
This is what I am trying to do in the body of the SP.
UPDATE ( SELECT t1.STATUS_ID, t2.CAMPAIGN_ID
FROM V_CAMPAIGN t1
INNER JOIN tc t2 ON t1.CAMPAIGN_ID = t2.CAMPAIGN_ID
) z
SET z.STATUS_ID = 4;
V_CAMPAIGN is a DB view, tc is my table variable
Presumably you are trying to update a subset of the V_CAMPAIGN records.
While in SQLServer it may be useful to define a 'temporary' table containing the subset and then operate on that it isn't necessary in Oracle.
Simply update the table with the where clause you would have used to define the temp table.
E.g.
UPDATE v_campaign z
SET z.status_id = 4
WHERE z.column_name = 'a value'
AND z.status <> 4
I assume that the technique you are familiar with is to minimise the effect of read locks that are taken while selecting the data.
Oracle uses a different locking strategy so the technique is mostly unnecessary.
Echoing a comment above - tell us what you want to achieve in Oracle and you will get suggestions for the best way forward.

How to get data from two databases in two servers with one SELECT statement?

I don't actually want to modify either database, just get the data.
I know how to connect to each database individually, with these connection strings:
Provider=SQLOLEDB.1;Data Source={0};Initial Catalog={1};Integrated Security=SSPI;Persist Security Info=False;
Provider=OraOLEDB.Oracle.1;Data Source={0};User ID={1};Password={2};Persist Security Info=True;
But how can I get this overlapping data together? Is that even possible, especially considering that one is Oracle and one is SQL Server? Or would it be better to do the SELECT statements on each database individually and then match them after?
For example, how would I get all students that are 10 years old and like the color blue?
Notice that all items in DatabaseB have an ID that maps to DatabaseA, but not the other way around.
I have done this with MySQL,Oracle and SQL server. You can create linked servers from a central MSSQL server to your Oracle and other MSSQL servers. You can then either query the object directly using the linked server or you can create a synonymn to the linked server tables in your database.
Steps around creating and using a linked server are:
On your "main" MSSQL server create two linked servers to the servers that contains the two databases or as you said database A and database B.
You can then query the tables on the linked servers directly using plain TSQL select statements.
To create a linked server to Oracle see this link: http://support.microsoft.com/kb/280106
A little more about synonyms. If you are going to be using these linked server tables in a LOT of queries it might be worth the effort to use synonymns to help maintain the code for you. A synonymn allows you to reference something under a different name.
So for example when selecting data from a linked server you would generally use the following syntax to get the data:
SELECT *
FROM Linkedserver.database.schema.table
If you created a synonym for Linkedserver.database.schema.table as DBTable1 the syntax would be:
SELECT *
FROM DBTable1
It saves a bit on typing plus if your linked server ever changed you would not need to go do changes all over your code. Like I said this can really be of benefit if you use linked servers in a lot of code.
On a more cautionary note you CAN do a join between two table on different servers. HOwever this is normally painfully slow. I have found that you can select the data from the different server into temp tables and joining the temp tables can generally speed things up. Your milage might vary but if you are going to join the tables on the different servers this technique can help.
Let me know if you need more details.
Which database are you using? Most of databases come with concept called dblinks. You have to create a dblink of database B in database A and then you can create a synonym (not a must but for ease) and use it as if it is table of database A.
Looks like a heterogeneous join (data on disparate servers/technologies etc).
As such, not straightforward. If you can make Namphibian's method work, go that way.
Otherwise, you need to gather the data from both tables to a common location (one or other of the servers 'in play', or a third server/technology solely for the purpose of co-locating the data). Then you can join the data happily. Many ETL Tools work this way, and this situation (almost) always involves redistribution of one or more of the tables to a common location before joining.
Oracle Data Integrator ETL tool does this, so does Talend Open Studio's tJoin component.
HTH
Try creating 3 Linq queries in Visual Studio. One for SQL Server, one for Oracle and one to combine the 2 database objects.
SELECT (things)
FROM databaseA.dbo.table t1
INNER JOIN databaseB.dbo.table t2 ON t1.Col1 = t2.Col2
WHERE t1.Col1 = 'something'
EDIT - This statement should meet the new requirements:
SELECT *
FROM databaseA.dbo.table t1
INNER JOIN databaseB.dbo.table t2 ON t1.ID = t2.ID
WHERE t1.Age = 10 AND t2.FavoriteColor = 'Blue'
If you want to select data from two different servers and database I would do a union and not a join as the data from one may be like apples and the other may be like oranges. You still would need to set up linked Servers and I believe you may link Oracle and SQL Server if after certain versions as shown but you could do something like this:
select ColA, ColB, ColC
from (ServerASQLServer).(DatabaseA).(schema).(table)
UNION
select ColA, ColB, ColC
from (ServerBOracleServer).(DatabaseB).(schema).(table)
If you perform inner joins your data must share data types to bind to or else they will be ommitted from the dataset returned. A union must just shared column data types but does not care on the logic. You are in essence saying: "Put these two sets of varying rows together based on their column logic matching."
But you were mentioning connection strings so I was curious if you would want to do it in a type of code method like .NET? I could provide an idea for that too possibly.
Assuming the databases are on the same server, you should be able to do something like this:
SELECT t.field1, t.field2
FROM database.schema.table t
JOIN database2.scheme.table2 t2
on t.id = t2.id
WHERE t2.field3 = ...
If the databases are on separate servers, look into using Linked Servers.
While I was having trouble join those two tables, I got away with doing exactly what I wanted by opening both remote databases at the same time. MySQL 5.6 (php 7.1) and the other MySQL 5.1 (php 5.6)
//Open a new connection to the MySQL server
$mysqli1 = new mysqli('server1','user1','password1','database1');
$mysqli2 = new mysqli('server2','user2','password2','database2');
//Output any connection error
if ($mysqli1->connect_error) {
die('Error : ('. $mysqli1->connect_errno .') '. $mysqli1->connect_error);
} else {
echo "DB1 open OK<br>";
}
if ($mysqli2->connect_error) {
die('Error : ('. $mysqli2->connect_errno .') '. $mysqli2->connect_error);
} else {
echo "DB2 open OK<br><br>";
}
If you get those two OKs on screen, then both databases are open and ready. Then you can proceed to do your querys.
On your specific question I will do something like first selecting from database A all the 10 year old kids then match them to the colors by the ID from database B. It should work, I havent tested this code on my server, but my sample below this code works. You can custom query by anything, color, age, whatever, even group them as you require to.
$results = $mysqli1->query("SELECT * FROM DatabaseTableA where age=10");
while($row = $results->fetch_array()) {
$theColorID = $row[0];
$theName = $row[1];
$theAge = $row[2];
echo "Kid Color ID : ".$theColorID." ".$theName." ".$theAge."<br>";
$doSelectColor = $mysqli2->query("SELECT * FROM DatabaseTableB where favorite_color=".$theColorID." ");
while($row = $doSelectColor->fetch_assoc()) {
echo "Kid Favorite Color : ".$row["favorite_color"]."<br>";
}
}
I have use this to switch back and forth for our programs without joining tables from remote servers and have no problem so far.
$results = $mysqli1->query("SELECT * FROM video where video_id_old is NULL");
while($row = $results->fetch_array()) {
$theID = $row[0];
echo "Original ID : ".$theID." <br>";
$doInsert = $mysqli2->query("INSERT INTO video (...) VALUES (...)");
$doGetVideoID = $mysqli2->query("SELECT video_id, time_stamp from video where user_id = '".$row[13]."' and time_stamp = ".$row[28]." ");
while($row = $doGetVideoID->fetch_assoc()) {
echo "New video_id : ".$row["video_id"]." user_id : ".$row["user_id"]." time_stamp : ".$row["time_stamp"]."<br>";
$sql = "UPDATE video SET video_id_old = video_id, video_id = ".$row["video_id"]." where user_id = '".$row["user_id"]."' and video_id = ".$theID.";";
$sql .= "UPDATE video_audio SET video_id = ".$row["video_id"]." where video_id = ".$theID.";";
// Execute multi query if you want
if (mysqli_multi_query($mysqli1, $sql)) {
// Query successful do whatever...
}
}
}
// close connection
$mysqli1->close();
$mysqli2->close();
I was trying to do some joins but since I got those two DBs open, then I can go back and forth doing querys by just changing the connection $mysqli1 or $mysqli2
It worked for me, I hope it helps... Cheers
As long as both databases are in the same server you can refer to tables with the database name :)
SELECT * FROM db1.table1
join
db2.tbable2
WHERE db1.table1.col1 = db2.table2.col1;

Import/Update data from Excel to SQL Server

I'm converting a database from Excel onto MS SQL server and am basically clueless.
The Excel file has column headings of GroupID, Name, Members, Remarks
The SQL table has the same fields.
When I update the SQL some records are totally new, so need to be appended, others need a column or two updated, while most records need nothing at all. So far I've taken the lazy way out & truncated the file & appended everything back in, but what's the proper way?
Import the file as a separate table and you can do all your updates from there. Depending on your version of SQL server you may be able to use the MERGE statement. It shouldn't take too long to knock up an insert, and an update statement.
Something like this for the update:
UPDATE o
SET name = i.name
FROM originaltablename o
INNER JOIN importedexceltablename i
ON o.GroupID = i.GroupID
WHERE o.name <> i.name
And something like this for the insert:
INSERT INTO originaltablename
SELECT i.*
FROM importedexceltablename i
LEFT JOIN originaltablename o
ON o.GroupID = i.GroupID
WHERE o.GroupID IS NULL
Be careful though, this is just an example to get you going as you haven't given enough information for a proper solution.

update one table using data from another table

I am trying to update my current table by drawing data from another table.
My database (dbo_finance)
column - test
The other database is assestsc and I am going to pull the data from column issuename1,
however I only want to pull the issuename1 when the field [MinSecClass] is = 9.
This is what I wrote
UPDATE dbo_finance
SET [dbo_finance].cusip9 = AssetsC.cusip
FROM dbo_finance INNER JOIN AssetsC ON dbo_finance.test = AssetsC.[IssueName1]
WHERE (AssetsC.MinSecClass = 9)
Thanks, first time really using SQL
Well I would use aliases, it's a good habit to get into:
UPDATE f
SET [dbo_finance].cusip9 = AssetsC.cusip
FROM dbo_finance f
INNER JOIN AssetsC a ON f.test = a.[IssueName1]
WHERE (a.MinSecClass = 9)
Now that will work fine if the assets table will only return one value for cuspid for each record. If this is a one to many relationship you may need to get more complex to truly get the answer you want.
I see several serious design flaws in your table structure. First joins fields that are dependant as something as inherently unstable as issue name are a very poor choice. You want PK and FK field to be unchanging. Use surrogate keys instead and a unique index.
The fact that you have a field called cusp9 indicates to me that you are denormalizing the data. Do you really need to do this? Do you undestand that this update will have to run in a trigger ever time the cuspid assoicated with MinSecClass changes? Whya re you denormalizing? Do you currently have performance problems? A denormalized table like this can be much more difficult to query when you need data from several of these numbered fields. Since you already have the data in the assets table what are you gaining except a maintenance nightmare by duplicating it?
UPDATE dbo_finance
SET cusip9 = (
SELECT A1.cusip
FROM AssetsC AS A1
WHERE dbo_finance.test = A1.IssueName1
AND AssetsC.MinSecClass = 9
)
WHERE EXISTS (
SELECT *
FROM AssetsC AS A1
WHERE dbo_finance.test = A1.IssueName1
AND A1.MinSecClass = 9
);
Because you're using SQL 2008, you can take advantage of the new(ish) MERGE statement.
MERGE INTO dbo_finance
USING (SELECT IssueName1, cusip FROM AssetsC WHERE MinSecClass = 9) AS source
ON dbo_finance.test = source.IssueName1
WHEN MATCHED THEN UPDATE SET dbo_finance.cusip9 = source.cusip;