I currently have a site (.net 2.0) with MS Access DB for data, within the access.mdb are 2 linked tables from another DB on the same site. - all of my code works fine and all my DB connections point to the one DB. I have a need now to achieve the same results, but don't want to create the links in the live DB. How can the same results be achieved via another method?
I looked at an example from: Syntax for Import Into from Different DBs - MS Access
My tables are large and don't think this is fastest way, I would think two connections and working with tables would be better, but I'm open to a proper way to accomplish this.
Here is my web.conf file with connections to the one DB.
<connectionStrings>
<clear />
<add name="OdbcServices" connectionString="Driver={Microsoft Access Driver (*.mdb)};Dbq=e:\LeaveDB.mdb;" />
</connectionStrings>
My end result I need to join 2 tables from different DB's something like:
SELECT username.table1, password.table1, fullname.table2 FROM Table1 INNER JOIN [;DATABASE=Z:\Docs\Test.mdb].Table2 ON username.table1 = username.table2;
Rather than create an "official" linked table (TableDef object) you might get away with simply creating a View that points to the table in the other database. I just tried this in C# and it seemed to work fine:
string myConnectionString;
myConnectionString =
#"Provider=Microsoft.ACE.OLEDB.12.0;" +
#"Data Source=C:\Users\Public\Database1.accdb;";
using (var con = new OleDbConnection())
{
con.ConnectionString = myConnectionString;
con.Open();
using (var cmd = new OleDbCommand())
{
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText =
#"CREATE VIEW otherTable AS " +
#"SELECT * FROM [;Database=C:\__tmp\main.accdb].otherTable";
cmd.ExecuteNonQuery();
}
con.Close();
}
That creates a "View" (saved query in Access) that seems to work just like a linked table.
Related
I'm working with VB.Net and Oracle 11g connecting thru ODAC to build a desktop application, it should be pretty simple but I'm facing a situation.
I have my security roles and users defined on the Oracle Database, my intent is to show menus according to each role (i.e administrator should see every menu while user only the relevant menus) my question is how can this be accomplished?
I was creating a separate table with usernames and roles but I bet there's a better way for handling this. Willing to take all suggestions at this point
You can use function DBMS_SESSION.IS_ROLE_ENABLED to get this information.
PL/SQL part would be like this
CREATE OR REPLACE FUNCTION IsRoleGranted(RoleName IN VARCHAR2) RETURN Integer IS
BEGIN
IF DBMS_SESSION.IS_ROLE_ENABLED(RoleName) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END IsRoleGranted;
In VB.NET you an call the function like this:
Dim cmd As OracleCommand
Dim con As OracleConnection
con = New ...
cmd = New OracleCommand("BEGIN IsRoleGranted(:role); END;" con)
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("res", OracleDbType.Byte, ParameterDirection.ReturnValue)
cmd.Parameters("res").DbType = DbType.Byte
cmd.Parameters.Add("role", OracleDbType.Varchar2, ParameterDirection.Input).Value = "MYAPP_ADMIN"
cmd.ExecuteNonQuery()
AdminMenu.Visible = CByte(cmd.Parameters("res").Value) = 1
DBMS_SESSION.IS_ROLE_ENABLED is easier to use than query view SESSION_ROLES because it also covers hierarchy of roles, i.e. when a role is granted to another role.
Filling a table in Oracle with the active directory roles and users is an often used solution.
Oracle has a DBMS_LDAP package to access Active Directory so you can get a list of groups for your app. I suggest a prefix for roles used in your app such as MyApp_admin, MyApp_user.
Then run a scheduled job to get the users that are in the groups and fill it into
something like this pseudo code table
TABLE GROUP_USER (
ID NUMBER(9) primary key,
GROUP_NAME VARCHAR2(250),
USER_NAME VARCHAR2(250));
This puts security at the enterprise level
allows the possibility of single sign on using sys_context('USERENV','OS_USER')
Hello guys i building a web app with asp.net and using sql ( MS SQL server 2000 ) and now after getting closer to finish i noticed that the sql part of my code taking huge amounts of space... and i was wondering what ways are there to make it easier to maintain? maybe even change to some other language?
Here is a simple example of the way my sql code is built ( there are some much longer commands in my code but they built this way) :
Dim connectionString As String = ConfigurationManager.ConnectionStrings("ConnectionString").ToString()
Dim query As String = "SELECT workerName FROM [poWorker] WHERE ( companyId = #companyId ) AND (workerId=#workerId) "
Using con As New SqlConnection(connectionString)
con.Open()
Using da As New SqlDataAdapter()
Using command As New SqlCommand(query, con)
command.Parameters.Add(New SqlParameter("#workerId", Session("userId")))
command.Parameters.Add(New SqlParameter("#companyId", Session("companyId")))
Dim ds As New DataSet()
da.SelectCommand = command
da.Fill(ds, "test")
If ds.Tables(0).Rows.Count = 1 Then
managerName = ds.Tables(0).Rows(0)(0).ToString()
End If
End Using
End Using
con.Close()
End Using
This is taking a lot of space and i got a lot of sql written this way. I am sure there is some solution in making it easier to maintain, probably using a newer technology? Maybe if i could figure out a way to call all the sql commands from 1-2 functions but so far i failed to do such a thing since there big differences between many of those.
In the example you give, you could simplify the code by using ExecuteScalar - as you are just returning a single value. For example:
Dim query As String = "SELECT workerName FROM [poWorker] WHERE ( companyId = #companyId ) AND (workerId=#workerId) "
Using con As New SqlConnection(connectionString)
con.Open()
Using command As New SqlCommand(query, con)
command.Parameters.Add(New SqlParameter("#workerId", Session("userId")))
command.Parameters.Add(New SqlParameter("#companyId", Session("companyId")))
managerName = command.ExecuteScalar().ToString();
End Using
con.Close()
End Using
A modern way to access databases from code is to use an ORM. The one that Microsoft provides with the .NET Framework is Entity Framework. This allows you to write your query like this:
Dim worker as Worker =
dbContext.Workers
.Where(Function (w) (w.companyId = Session("companyId") and
w.workerId = Session("userId")))
.SingleOrDefault()
If worker IsNot Nothing Then
managerName = worker.workerName
End If
This approach also provides a far more robust approach to dynamic queries as opposed to piecing SQL strings together. For example, you can dynamically swap out Where clauses, OrderBy clauses, and so on, and still have completely typesafe code.
Entity Framework does not have builtin support for SQL Server 2000, but apparently there is a workaround.
The modern way is to no use SQL directly, but rather an OR-Mapper such as Entity Framework that allows you to query using Linq.
The query you show above would the be reduced to something shorter:
using(new context = MyAppDbContext())
{
var workerId = Session["userId"];
var companyId = Session["companyId"];
managerName = context.PoWorker
.Single(w => w.companyId == companyId && w.workerId == workerId)
.workerName;
}
Sorry for using C# syntax, but I hope you can figure out the intention.
SQL Server 2005. Visual Studio 2010. ASP.NET 2.0 Web Application
This is a web application that supports multiple languages, one of them is Korean. I have “langid” in the query string to differentiate different languages, if langid=3 it is Korean.
In my code behind’ C# code, I read a table using this query:
"select * from Reservations where rsv_id = 1234"
There is a column named "rsv_date" in the table which is reservation date, of type datetime. In the db table its value is "11/22/2012 4:14:37 PM". I checked this in SQL server management studio. But when I read it out, I got "2012-11-22 오후 4:14:37"! Where does that Korean “오후” come from??? Is it because of some culture setting anywhere? But I don’t see where, either in my code or in SQL Server. This caused problem for me, because when I modify this record, it will try to write "2012-11-22 오후 4:14:37" to the db, which of course SQL server reports error.
My original code:
Hashtable reservation = new Hashtable();
SqlCommand sqlCommand = null;
SqlDataReader dataReader;
string queryCommand = "select * from Reservations where rsv_id = #RsvID";
sqlCommand = new SqlCommand(queryCommand, getConnection());
sqlCommand.Connection.Open();
sqlCommand.Parameters.AddWithValue("#RsvID", rsvID);
dataReader = sqlCommand.ExecuteReader();
while (dataReader.Read())
{
reservation["rsvID"] = dataReader["rsv_id"];
reservation["rsvCode"] = dataReader["rsv_code"];
reservation["rsvType"] = dataReader["rsv_type"];
reservation["rsvDate"] = dataReader["rsv_date"]; // where does Korean come from?
...
}
It's a common misunderstanding that you can "check" the format of datetime fields in the database.
The format you see on screen will always depend on the client, even if the client is "SQL server management studio".
In the database, the datetime is stored in a binary format that very few need to know.
So, the Korean characters are from the client, in this case your own program.
And Yes, they will depend on some culture setting somewhere.
Your example doesn't show what happens to reservation["rsvDate"] , where is the value displayed with the Korean characters ?
How are you trying to write the value with Korean characters to the database ?
To avoid Korean characters you could use .ToString(CultureInfo.InvariantCulture) where you use the Date value.
We're working on making our application 100% localizable, and we're mostly there. However, we occasionally find an English string still hard-coded in stored procedures. (We're on SQL Server 2005 by the way.) We have thousands of stored procedures, so going through them by hand is impractical. I'm trying to think of the most accurate means of automating a search.
Now, I know there's no means to search for "English" strings - but searching for strings bounded by single quotes and perhaps 20+ characters long should flush MOST of them out. Good enough for our purposes now. But I'm anticipating a lot of false-positives in the comments of the stored procedures, too.
So how would you approach this? Would SMO let me tease apart the SQL in a stored procedure from the comments in it? Do I have to use OBJECT_DEFINITION() and start hacking out some terrifying regular expressions?
Much appreciated in advance, folks.
Another thought: Microsoft provides, with Visual Studio, an assembly that can parse SQL. I've used it, and it's fairly simple to use. You might be able to use it to parse the text of your stored procedures; it can return a list of the various tokens in your statements, including the type of the token. So, it should be able to help you differentiate between what is a string of text you might be interested in vs. what is part of a comment and can be ignored. There are more details here: http://blogs.msdn.com/b/gertd/archive/2008/08/21/getting-to-the-crown-jewels.aspx.
Basically, from .NET, you'd open a connection to your database and query syscomments for your stored procedures' text. You'd loop through each procedure and parse it using these parser. Then you'd use the Sql100ScriptGenerator to get the tokens out of the parsed text, loop through the tokens and look for tokens whose types are either ASCII or Unicode string literals. For those strings, check their length to see if it's 20+, and if it is, flag the strings and the procs as needing further review.
I played around with it a bit, and here is a very raw example to illustrate the basic principle:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Data.Schema;
using Microsoft.Data.Schema.ScriptDom;
using Microsoft.Data.Schema.ScriptDom.Sql;
namespace FindHardCodedStrings
{
class Program
{
static void Main(string[] args)
{
using (SqlConnection conn = new SqlConnection())
{
SqlConnectionStringBuilder bldr = new SqlConnectionStringBuilder();
bldr.DataSource = "localhost\\sqlexpress";
bldr.InitialCatalog = "msdb";
bldr.IntegratedSecurity = true;
conn.ConnectionString = bldr.ConnectionString;
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "select [text] from syscomments";
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
TSql100Parser parser = new TSql100Parser(false);
Sql100ScriptGenerator gen = new Sql100ScriptGenerator();
gen.Options.SqlVersion = SqlVersion.Sql100;
foreach (DataRow proc in ds.Tables[0].Rows)
{
string txt = proc[0].ToString();
using (System.IO.TextReader sr = new System.IO.StringReader(txt))
{
IList<ParseError> errs;
IScriptFragment frag = parser.Parse(sr, out errs);
if (null == frag)
continue;
IList<TSqlParserToken> tokens = gen.GenerateTokens((TSqlFragment)frag);
foreach (TSqlParserToken token in tokens)
{
if (token.TokenType == TSqlTokenType.UnicodeStringLiteral || token.TokenType == TSqlTokenType.AsciiStringLiteral)
{
if (token.Text.Length >= 20)
Console.WriteLine("String found: " + token.Text);
}
}
}
}
}
}
}
}
We resolved a problem stemming from this by creating SQL Servers in different language/region settings and running our sp's, noting which ones broke.
This may not be the most elegant solution but we were able to do it quickly because of the limited different locality settings we support.
I basically need to know how to import SQL code into Access. I've tried one way but that requires me to do one table and one value at a time which takes a lot of time.
Can anyone help?
If you are trying to import data, rather than SQL code (see Duffymo's response), there are two ways.
One is to go where the data is and dump a .CSV file and import that, as Duffymo responded.
The other is to create a table link from the Access database to a table in the source database. If the two databases will talk to each other this way, you can use the data in the remote table as if it were in the Access database.
Well, some days ago I needed to shift data from an Access database to SQL (reverse of what you're doing). I found it simpler to write a simple script that would read data from my access database and insert it into SQL.
I don't think doing what you need to do is any different.
I don't know if it will help, but I posting my code (It's a simple C# function). You can just change the connections and it will work. Of course I only had 3 fields so I hard-coded them. You can do the same for your db schema.
protected void btnProcess_Click(object sender, EventArgs e)
{
//Open the connections to the access and SQL databases
string sqlDBCnn = #"Data Source=.\SQLEXPRESS;Integrated Security=True;AttachDBFileName=|DataDirectory|\mydb.mdf;user instance=true";
string accessDBCnn = #"Provider=Microsoft.Jet.OleDB.4.0;Data Source=C:\mydb.mdb";
OleDbConnection cnnAcc = new OleDbConnection(accessDBCnn);
cnnAcc.Open();
SqlConnection cnnSql = new SqlConnection(sqlDBCnn);
cnnSql.Open();
SqlCommand cmSql = new SqlCommand("DELETE tablename", cnnSql);
cmSql.ExecuteNonQuery();
//Retrieve the data from the Access Database
OleDbCommand cmdAcc = new OleDbCommand("SELECT * FROM tablename", cnnAcc);
OleDbDataReader drAcc = cmdAcc.ExecuteReader();
using (drAcc)
{
if (drAcc.HasRows)
{
//Loop through the access database records and add them to the database
while (drAcc.Read())
{
SqlCommand cmdSql = new SqlCommand("INSERT INTO tablename(Category, Head, Val) VALUES(#cat,#head,#val)",cnnSql);
SqlParameter parCat = new SqlParameter("cat",System.Data.SqlDbType.VarChar,150);
SqlParameter parHead = new SqlParameter("head",System.Data.SqlDbType.VarChar,150);
SqlParameter parVal = new SqlParameter("val",System.Data.SqlDbType.VarChar);
parCat.Value = drAcc["Category"].ToString();
parHead.Value = drAcc["Head"].ToString();
parVal.Value = drAcc["Val"].ToString();
cmdSql.Parameters.Add(parCat);
cmdSql.Parameters.Add(parHead);
cmdSql.Parameters.Add(parVal);
cmdSql.ExecuteNonQuery();
}
}
}
lblMsg.Text = "<p /> All Done Kapitone!";
}
SQL code? Or data? "one table and one value" makes me think it's the latter. If so, I'd suggest dumping the data out into a .csv file and importing that into Access tables.
Or maybe using a tool like Microsoft's DTS to map and move the data between sources. That would be the best idea.
I guess you are talking about "importing" both structure and data from SQL to ACCESS. ACCESS does not accept standard TSQL scripts that you could generate directly from your SQL Database. There are some commercial products like EMS that can more or less do the job for you. EMS has a data exporter module that can take your SQL data in different formats, including Access.
Another way would be to open an Access file and write some basic VBA code, taking advantage of the DoCmd.TransferDatabase method, where you can link OR copy tables from other databases into Access.
I forgot if these methods also allow the transfer of a 'clean' database model, including primary keys and relations... You'll have to give it a try.