Detach and take a copy database and attach it to SQL Server - sql-server

I am trying to copy a database file using file management concept in vb.
My code is:
IO.File.Copy(MukilCommon.APP_PATH & "\" & CurrentDbName & ".mdf", MukilCommon.APP_PATH & "\" & CurrentDbName & "_" & yearStr & ".mdf")
IO.File.Copy(MukilCommon.APP_PATH & "\" & CurrentDbName & ".ldf", MukilCommon.APP_PATH & "\" & CurrentDbName & "_" & yearStr & ".ldf")
My code is copied a database from new database on e:, like this:
sample.mdf
sample.ldf
sample_2016.mdf
sample_2016.ldf
I used this code for attach my copied database in SQL Server.
db1.Execute("EXEC sp_attach_db #dbname = '" & CurrentDbName & "_" & yearStr & "', #filename1 = '" & MukilCommon.APP_PATH & "\" & CurrentDbName & "_" & yearStr & ".mdf', #filename2 = '" & MukilCommon.APP_PATH & "\" & CurrentDbName & "_" & yearStr & ".ldf'")
But I get this message.
Can't attach a file name, "sample" database is already exists in SQL Server.
Actually the copied file has try to attached on original database. How to I attach this database?

My suggestions:
Put the files in different folders, you have to keep mdf and ldf files with the same name, use this script:
USE [master]
GO
CREATE DATABASE [Simple_2017] ON
( FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\2017\Simple.mdf' ),
( FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\2017\Simple_log.ldf' )
FOR ATTACH
GO
don't use sp_attach_db

As I could understand, you have data and log files of a detached database and you want to attach this database on a SQL Server instance.
From the error, I understand that there is already a database named "sample" on your SQL Server instance
So, if you want to attach a new database, you can choose a new name for your database to attach. Maybe you can call it sample2
Since you have already tried to detach, I could guess your data files are in a seperate folder than the existing sample database files exist
You can keep these files on seperate folders, so you can use the same fille names for example TestDB.mdf for both sample database and sample2 database
Then you can execute your code like
EXEC sp_attach_db #dbname = N'sample2',
#filename1 =
N'C:\NewDataFolder\TestDB.mdf',
#filename2 =
N'C:\NewDataFolder\TestDB_log.ldf';

Related

Bulk Insert, Invalid Object Error (table name), Excel VBA to SQL Server

I am trying to bulk load from a CSV file to an SQL Server (both Excel and SQL Server are sitting on my laptop). I am doing this via Excel VBA using the "bulk insert" statement. I keep getting a run-time error of invalid object name for my table.
I have tested the SQL in studio management and it works fine
The table name is definitely correct
I have tested using the different file formats and I get same error
"insert into..." statement works fine from Excel VBA just not the "BULK INSERT"
connServer.Open "Provider=SQLOLEDB;Data Source=" & pstrServer & ";Initial Catalog=" & pstrDBS & ";integrated security=sspi;"
strSQLQuery = "BULK INSERT tbl_q_member " & _ "FROM 'C:\test\bulk.csv' " & _ "WITH (FIRSTROW = 2, FIELDTERMINATOR = ',',ROWTERMINATOR = '\n', TABLOCK)"
connServer.Execute strSQLQuery
The runtime error is
'-2147217865 (800440e37)
Invalid object name 'tbl_q_member'

Create database in SQL Server (only once) using VBA Excel

I would like to create a database in SQL server using VBA (Excel) just the first time that I will run the code. So the second time I run the code, the database will exist, and it will not create another one.
#abarisone
`Public Sub CreateDBTable()
Dim dbConnectStr As String
Dim Catalog As Object
Dim cnt As ADODB.Connection
Dim dbName As String
Dim tblName As String, ServerName As String, UserID As String, pw As String
tblName = shControl.Range("B5") 'Table Name
ServerName = "SERVICESWS15" 'Enter Server Name or IP
dbName = shControl.Range("B4") 'Enter Database Name
UserID = "" 'Leave blank for Windows Authentification
pw = "" 'Leave blank for Windows Authentification
dbConnectStr = "Provider=SQLOLEDB;Data Source=" & ServerName & ";Initial Catalog=" & dbName & ";User Id=" & UserID & ";Password=" & pw & ";"
Set Catalog = CreateObject("ADOX.Catalog")
Catalog.Create dbConnectStr
Set Catalog = Nothing
Set cnt = New ADODB.Connection
With cnt
.Open dbConnectStr
.Execute "CREATE TABLE " & tblName & " (KEY nvarchar(100) NOT NULL, " & _
"Date nvarchar(100) NOT NULL, " & _
"PRIMARY KEY (KEY));"
End With
Set cnt = Nothing
End Sub
`
There is an error in this line:
Catalog.Create dbConnectStr
Error: No such interface supported
It's not very complicated. First make sure that you are referring to the appropriate ADO library like here on the screenshot.
Then your have certain building blocks you will have to use: first make a Connection object (with a connection string), then make a Command object, and last but not least use the ExecuteNonQuery method of Command on your connection object. It does what the name says: executes an SQL command without having a RecordSet as a return object. See examples in the documentation starting from here.
I have not tried it before, but for this to happen without error, you will probably have to set your connection string to the system database called "Master" if working on MS SQL Server.
Of course, the SQL commands you will have to execute are (1) check if the database exists, (2) create db and tables if not.
Then you can create your "normal" Connection object to your database.
WARNING: to be able to create a database, your technical user defined in the VBA script must have high (system admin) privileges which is definitely a HUGE RISK even if you protect your excel. If it's not a sandbox environment, DO NOT DO IT!

In MS Access SQL Server Linked Table pass through query

I have a query against a linked table in MS Access that uses the getdate() function of SQL Server. However, I get this error when I attempt to run the query:
Undefined function GetDate in function
How do I create a linked table that allows the use of SQL Server T-SQL syntax? I see that this is called a pass through query but I don't know how to set it up to use the connection on the linked table as a pass through query.
Currently using Access 2010. The query is:
select getdate()
If it helps, I used the following vba code that generates the table link to SQL Server:
Function LinkTable(LinkedTableAlias As String, Server As String, Database As String, SourceTableName As String, OverwriteIfExists As Boolean, Username As String, Password As String)
'This method will also update the link if the underlying table definition has been modified.
If (InStr(1, LinkedTableAlias, "MSys") > 0) Then
Log "Skipping " & LinkedTableAlias
Exit Function
End If
'The overwrite parameter will cause it to re-map/refresh the link for LinktedTable Alias, but only if it was already a linked table.
' it will not overwrite an existing query or local table with the name specified in LinkedTableAlias.
'Links to a SQL Server table without the need to set up a DSN in the ODBC Console.
Dim tdfLinked As DAO.TableDef
' Open a database to which a linked table can be appended.
Dim dbsCurrent As Database
Set dbsCurrent = CurrentDb()
'Check for and deal with the scenario ofthe table alias already existing
If TableNameInUse(LinkedTableAlias) Then
'If InStr(dbsCurrent.TableDefs(LinkedTableAlias).Connect, "AccessBackup") Then
' Exit Function
'End If
If (Not OverwriteIfExists) Then
Log "Can't use name '" + LinkedTableAlias + "' because it would overwrite existing table."
Exit Function
End If
'delete existing table, but only if it is a linked table
'If IsLinkedTable(LinkedTableAlias) Then
dbsCurrent.TableDefs.Delete LinkedTableAlias
dbsCurrent.TableDefs.Refresh
'Else
' Log "Can't use name '" + LinkedTableAlias + "' because it would overwrite an existing query or local table."
' Exit Function
'End If
End If
'Create a linked table
Set tdfLinked = dbsCurrent.CreateTableDef(LinkedTableAlias)
tdfLinked.SourceTableName = SourceTableName
tdfLinked.Connect = "ODBC;DRIVER={SQL Server};SERVER=" & Server & ";DATABASE=" & Database & ";UID=" & Username & ";PWD=" & Password & ";"
On Error Resume Next
dbsCurrent.TableDefs.Append tdfLinked
If (err.Number = 3626) Then 'too many indexes on source table for Access
err.Clear
On Error GoTo 0
If LinkTable(LinkedTableAlias, Server, Database, "vw" & SourceTableName, OverwriteIfExists, Username, Password) Then
Log "Can't link directly to table '" + SourceTableName + "' because it contains too many indexes for Access to handle. Linked to view '" & "vw" & SourceTableName & "' instead."
LinkTable = True
Else
Log "Can't link table '" + SourceTableName + "' because it contains too many indexes for Access to handle. Create a view named '" & "vw" & SourceTableName & "' that selects all rows/columns from '" & SourceTableName & "' and try again to circumvent this."
LinkTable = False
End If
Exit Function
End If
On Error GoTo 0
'** Turn on error handling
On Error GoTo ErrorHandler:
tdfLinked.RefreshLink
LinkTable = True
Exit Function
ErrorHandler:
Log "refreshlink failed for " & tdfLinked.Name
LinkTable = True
I don't quite understand this statement:
How to I create a linked table that allows the use of SQL Server T-SQL
syntax?
But this is how you convert an existing MS Access querydef to a pass through query:
Go to design mode in the query, press the Query menu command, then SQL Specific then Pass Through
See this for screenshots.
http://www.mssqltips.com/sqlservertip/1482/microsoft-access-pass-through-queries-to-sql-server/
The reason why you are getting the error is that GETDATE() is not a function inside MSAccess. You probably need Now() to get the date and time or you may use Date() which provides the date
Here's a quick and dirty VBA way to create a pass-through query:
Set qdf = CurrentDb.CreateQueryDef("testqry")
' this is just your connection string
qdf.Connect = "ODBC;Driver={SQL Server};Server=MSSQL1; Database=MyDB;Trusted_Connection=Yes"
'anything here gets passed directly to and executed on the SQL Server
qdf.SQL = "select getdate()"
Set qdf = Nothing
Now you can use "testqry" as if it's any other Access query (as far as SELECTing from it goes, anyway)
Simple save your t-sql query as a pass-though
Select GetDate()
Then in VBA code, you can go:
TheSqlDate = currentdb.QueryDefs("qPass").OpenRecordset()(0)
Using ADO, and hardcoding connection strings, and the HUGE whacks of other code posted here is just a way to rack up billable hours and create world poveity. My posted solution IS ONLY ONE LINE OF CODE!

Import Email from AD Mailbox

We have an old legacy SQL 2000 server (the last in the farm) – We’ve been unable to get rid of this server as it uses xp_findnextmsg, xp_readmail etc to monitor a mailbox (via mapi) and import all email to that address into a database. The database contains simple tables that store "from", "to", "subject", "body", "Sent Date" & so on.
As you may know, the procs above are no longer in use in SQL 2005+
This table is read from dozens of internal systems, for instance emails to this mailbox can be automatically picked up by our helpdesk systems & create calls etc.
My question is this: what it the easiest / modern way of doing this in SQL 2008+? Is it going to be a case of writing a .net binary / service that will use smtp or something to connect to a mailbox and insert the data into SQL or is there a simpler way to do it? (SSIS / 3rd party tools / pre-existing code / projects?)
Just thought I’d ask before i start writing something – no point re-inventing the wheel as it were.
PS: The Mailbox in question is an exchange 2010 mailbox.
Edit: This functionality was hinted to be re-introduced in 2008 & dbmail: http://connect.microsoft.com/SQLServer/feedback/details/126167/xp-readmail-replacement-for-sql-2005 but it looks like it failed to materialise!
Edit 2: I've just found a decent code sample here that utilises the new web services in exchange 2007+: http://social.msdn.microsoft.com/forums/en-US/sqltools/thread/dd2b465b-b1d2-4c0d-82ec-c36c6c482d5d - experimenting in progress (has anyone ever worked with SQL and the Exchange web services?)
Edit 3: All done! I knocked up a .net service that sits on our exchange server and monitors a mailbox & pushes any new mail into SQL. Incase others have a similar question and need some sample code to get started - here is some rough code (chopped out of my service - replaced parameterised SQL with basic dynamic SQL for easy reading): (Note: you’ll need the EWS API 1.1 dll)
Imports Microsoft.Exchange.WebServices.Data
Dim ExchangeUrl As String = "https://DOMAIN.co.uk/ews/exchange.asmx"
Dim service As New ExchangeService(ExchangeVersion.Exchange2010_SP1)
service.Url = New Uri(ExchangeUrl)
service.Credentials = New WebCredentials("USER#DOMAIN.CO.UK", "PASSWORD")
Dim findResults As FindItemsResults(Of Item) = service.FindItems(WellKnownFolderName.Inbox, New ItemView(1000))
If findResults.Count > 0 Then
service.LoadPropertiesForItems(findResults.Items, New PropertySet(BasePropertySet.FirstClassProperties))
End If
For Each item As Item In findResults.Items
Dim CurrentEmail As EmailMessage = item
'#### Grab Email Information
E_ID = CurrentEmail.InternetMessageId.ToString()
If CurrentEmail.Sender.Address.ToString() <> "" Then
E_From = Replace(CurrentEmail.Sender.Address, "'", "''")
Else
E_From = Replace(CurrentEmail.Sender.Name, "'", "''")
End If
E_From = Replace(CurrentEmail.Sender.Address, "'", "''")
E_To = Replace(CurrentEmail.DisplayTo, "'", "''")
E_CC = Replace(CurrentEmail.DisplayCc, "'", "''")
E_Subject = Replace(CurrentEmail.Subject, "'", "''")
E_Body = Replace(CurrentEmail.Body.Text, "'", "''")
E_Received = CurrentEmail.DateTimeReceived.ToString("dd/MM/yyyy HH:mm:ss")
E_Sent = CurrentEmail.DateTimeSent.ToString("dd/MM/yyyy HH:mm:ss")
'#### Save the email into SQL
If SqlQuery("INSERT INTO tbl_Emails ([MessageID], [From], [To], [CC], [Subject], [Body], [Received], [Sent]) VALUES ('" & E_ID & "', '" & E_From & "', '" & E_To & "', '" & E_CC & "', '" & E_Subject & "', '" & E_Body & "', CONVERT(DATETIME, '" & E_Received & "', 103), CONVERT(DATETIME, '" & E_Sent & "', 103))") = True Then
item.Delete(DeleteMode.HardDelete)
End If
Next
The first thing that comes to mind for me is SQL CLR. MAPI is not specifically supported in .net (at least to my knowledge), although there are work arounds.
Reading from an exchange mailbox, luckily, is supported in host of situations.
BTW,I've found working with email in .net to be relatively pain free.

How to copy SQL Server database from Access

We have an Access UI to Sql Server database. The user connects to many databases (containing the same tables with different data), can choose between them. We use this for versioning. We want to make him able to copy and delete databases right from Access UI. He should be able to copy at least to the same server, and ideally also to other server.
A Backup and restore is probably going to be your best bet. There is another way as well. But there will be some restrictions.
You can detach the DB you want to copy, make a copy of the files attach the old one, and attach the new one as a new DB. Your problem will be because you are using Access to connect to the DB, you will not be able to detach it because there is a connection to it, and all connections must be dropped before you can detach it.
Dropping the DB (delete it) will have the same problem. It won't drop unless you there is no connections on the DB.
This is my final solution:
Dim conn As New ADODB.Connection
conn.ConnectionString = "Provider=SQLOLEDB;Data Source=" dbServer & ";" _
& "User ID=" & user & ";Password=" & password
conn.Open
' backup
conn.Execute "BACKUP DATABASE [" & sourceDb & "] TO [backup device] WITH NOFORMAT, NOINIT, NAME = N'backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10"
' restore
conn.Execute "RESTORE DATABASE [" & targetDb & "] FROM [abcosting temporary backup] WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10, " & mdf_move & ", " & ldf_move

Resources