I am using the below code to backup a Database on my local SqlExpress database.
procedure RestoreScoreDb(DBName,OldName,BackName : String);
var
cmd : WideString;
SqlBackupDir : String;
SqlDataDir : String;
begin
Try
ConnectionMaster.Connected := False;
ConnectionMaster.Close;
ConnectionMaster.ConnectionString := 'Provider=SQLNCLI11.1;Integrated Security="";Persist Security Info=False;User ID=SA;Password=Tccc1234;OLE DB Services=-2;Initial Catalog="master";Data Source=\SQLEXPRESS;Initial File Name="";Packet Size=4096;Auto Translate=True;Server SPN=""';
SqlBackupDir := ReadIniStr(IniCfg,'Dir','SqlBackup');
SqlDataDir := ReadIniStr(IniCfg,'Dir','SqlData');
cmd := 'RESTORE DATABASE '+DBName;
cmd := Cmd + ' FROM DISK = N'''+SqlBackupDir+'\'+BackName+'''';
cmd := Cmd + ' WITH FILE = 1';
cmd := cmd + ' , MOVE N'''+OldName+''' TO N'''+SqlDataDir+'\'+DBName+'.mdf''';
cmd := cmd + ' , MOVE N'''+OldName+'_log'' TO N'''+SqlDataDir+'\'+DBName+'.ldf''';
cmd := cmd + ' , NOUNLOAD, REPLACE, STATS = 10';
CmdRestore.CommandText := cmd;
CmdRestore.Connection := ConnectionMaster;
CmdRestore.Execute;
except
on E: Exception do
writeln(LogFile,'RestoreScoreDb = '+E.Message);
end;
end;
The Restore command is
cmd ='RESTORE DATABASE score_import FROM DISK =
N''C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\Backup\score_import.bak''
WITH FILE = 1 , MOVE N''score_import'' TO
N''C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\score_import.mdf'' ,
MOVE N''score_import_log'' TO N''C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\score_import.ldf'' ,
NOUNLOAD, REPLACE, STATS = 10'
When I copy and paste into management studio it restore the table without trouble. but when I run this code I get an Error:
User does not have permission to RESTORE database "score_import"
SA has full permission. Any idea what I am missing? Delphi XE6, Windows 10 Sql 2012.
Thanks to Embarcadero support. They could reproduce my problem and resolved it by removing Integrated Security="" from the connection string. If you are interested in why, do a Google search for "ADO Integrated Security".
Related
I want to restore a SQL Server .bak backup file in InnoSetup.
Here is the code I use:
try
ExtractTemporaryFile ('mydb.bak');
ADOConnection := CreateOleObject('ADODB.Connection');
ADOConnection.ConnectionString :=
'Provider=SQLOLEDB;' + // provider
'Data Source=DESKTOP-UE6ST1P\RMPRO;' + // server name
'Initial Catalog=master ;' + // default database
'User Id=sa;' + // user name
'Password=mypass;'; // password
ADOConnection.Open;
try
ADOCommand := CreateOleObject('ADODB.Command');
ADOCommand.ActiveConnection := ADOConnection;
ADOCommand.CommandText := 'RESTORE DataBase mydb FROM DISK = ' + QuotedStr(ExpandConstant('{tmp}\mydb.bak'));
ADOCommand.CommandType := adCmdText;
ADOCommand.Execute(NULL, NULL, adCmdText or adExecuteNoRecords);
finally
ADOConnection.Close;
end;
except
MsgBox('Error', mbError, MB_OK);
end;
end;
When I run this code get this error
Exception: Microsoft OLE DB Provider for SQL Server: Cannot open backup device 'C:\Users\sina\AppData\Local\Temp\is-QADA6.tmp\mydb.bak'. Operating system error 5 (Access is denied).
How I can handle access denied in InnoSetup? I run the setup in "Run as Administrator" and turn UAC off, but I still have this problem.
Am trying to restore the database from python 3.7 in Windows using below script.
Drop database functions correctly as expected.
The restore database doesn't work as expected, database always shows "Restoring...." and never completes.
Database files are there in the specified path, but database is not usable.
How to fix this?
import pyodbc
try:
pyconn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER=MY-LAPTOP\\SQLEXPRESS;DATABASE=master;UID=sa;PWD=sa123')
cursor = pyconn.cursor()
pyconn.autocommit = True
sql = "IF EXISTS (SELECT 0 FROM sys.databases WHERE name = 'data_test') BEGIN DROP DATABASE data_test END"
pyconn.cursor().execute(sql)
sql = """RESTORE DATABASE data_test FROM DISK='G:\\dbbak\\feb-20-2020\\data_test_backup_2020_02_20_210010_3644975.bak' WITH RECOVERY,
MOVE N'Omnibus_Data' TO N'd:\\db\\data_test.mdf',
MOVE N'Omnibus_Log' TO N'd:\\db\\data_test_1.ldf';"""
print(sql)
pyconn.cursor().execute(sql)
while pyconn.cursor().nextset():
pass
pyconn.cursor().close()
except Exception as e:
print(str(e))
You're not using a single cursor, and so your program is exiting before the restore is complete, aborting it in the middle.
Should be something like:
conn = pyodbc.connect(' . . .')
conn.autocommit = True
cursor = conn.cursor()
cursor.execute(sql)
while cursor.nextset():
pass
cursor.close()
0
After hours I found solution. It must be performed no MASTER, other sessions must be terminated, DB must be set to OFFLINE, then RESTORE and then set to ONLINE again.
def backup_and_restore():
server = 'localhost,1433'
database = 'myDB'
username = 'SA'
password = 'password'
cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE=MASTER;UID='+username+';PWD='+ password)
cnxn.autocommit = True
def execute(cmd):
cursor = cnxn.cursor()
cursor.execute(cmd)
while cursor.nextset():
pass
cursor.close()
execute("BACKUP DATABASE [myDB] TO DISK = N'/usr/src/app/myDB.bak'")
execute("ALTER DATABASE [myDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;")
execute("ALTER DATABASE [myDB] SET OFFLINE;")
execute("RESTORE DATABASE [myDB] FROM DISK = N'/usr/src/app/myDB.bak' WITH REPLACE")
execute("ALTER DATABASE [myDB] SET ONLINE;")
execute("ALTER DATABASE [myDB] SET MULTI_USER;")
I am trying to do a full backup for an MSSQL database using go.
However, I tested the connection to the MSSQL server and it works like charm!
By executing also a query into the code SELECT ##VERSION
It gives me the version and that has been connected to mssql using the credentials in the code below.
By running a query BACKUP DATABASE name_db TO DISK = '/tmp/database.bak' it fails with the following error
Error with Backing up the DBmssql: BACKUP DATABASE is terminating abnormally
I am sure that I am missing something, any ideas/thoughts would be much appreciated.
BTW, I am on Ubuntu 16.04 and the mssql is installed there, I am using go version 1.9.
This is my code:
package main
import (
_ "github.com/denisenkom/go-mssqldb"
"database/sql"
"context"
"log"
"fmt" )
var server = "server_url"
var port = 1433
var user = "user"
var password = "pass"
var db *sql.DB
func main() {
var err error
// Create connection string
connString := fmt.Sprintf("server=%s;user id=%s;password=%s;
port=%d", server, user, password, port)
// Create connection pool
db, err = sql.Open("sqlserver", connString)
if err != nil {
log.Fatal("Error creating connection pool: "
+ err.Error())
}
log.Printf("Connected!\n")
defer db.Close()
Backup()
//Restore()
}
func Backup(){
ctx := context.Background()
err := db.PingContext(ctx)
if err != nil {
log.Fatal("Error pinging database :( " + err.Error())
}
var result string
err = db.QueryRowContext(ctx, "BACKUP DATABASE tempdb
TO DISK= '/tmp/Backup.bak' WITH NOFORMAT, NOINIT,
SKIP, NOREWIND, NOUNLOAD, STATS = 10;").Scan(&result)
//err = db.QueryRowContext(ctx, "select ##version").Scan(&result)
if err != nil {
log.Fatal("Error with Backing up the DB", err.Error())
}
fmt.Printf("%s\n",result)
}
I have found the solution which is very silly.. You can find it in the 1st reply.
That was obvious though, the code is clean and working as expected.
The only issue was from MSSQL, where it have a specific value set for the timeout queries.
That's why I succeeded executing other SQL queries like: SELECT ##VERSION from the example above in the Q.
Though, I set the value of the timeout for remote queries to 0 this SQL query:
EXEC SP_CONFIGURE 'remote query timeout', 0
reconfigure
EXEC sp_configure
The 0 in remote query timeout means that the timeout is unlimited.
The issue was from MSSQL and os , try query first on SQL Server Management Studio to explane where problem come from.
now, change this :
(
err = db.QueryRowContext(ctx, "BACKUP DATABASE tempdb
TO DISK= '/tmp/Backup.bak' WITH NOFORMAT, NOINIT,
SKIP, NOREWIND, NOUNLOAD, STATS = 10;").Scan(&result)
)
to
(
err = db.QueryRowContext(ctx, "BACKUP DATABASE tempdb
TO DISK= '/tmp/Backup.bak' WITH NOFORMAT, NOINIT,
SKIP, NOREWIND, NOUNLOAD, STATS = 10;").Err()
)
becouse db.QueryRowContext expected to return at most one row
and backup Query dont return any row
I have 4 pc's. 2 have full setup SQ Server 2012 setup, 1 as all but the data base setup, and 1 does not have SQL setup at all. The 3 with SQL setup connects to the one I call the subserver that has the data base setup on. The one without SQL installed on it at all does not connect throws an exception.
Here is my connection string.
Provider=SQLNCLI11;Integrated Security="";Persist Security Info=False;User ID=sa;password=Xxxx1234;OLE DB Services=-2;Initial Catalog=score_data;Data Source=192.168.9.25,1433;Initial File Name="";Packet Size=4096;Auto Translate=True;Server SPN="";
Here is my Delphi code used to create this string and connect
function TFrmTb2.ConnectToSqlDB(Var DataBase : TADOConnection; Catalog : String; Var Msg : ShortString) : Boolean;
var
cntStr : String;
begin
msg := '';
CntStr := DataBase.Name;
if not DataBase.Connected then
begin
if Not DataBase.Connected then
begin
with FrmTb2 do
begin //Edit ConfigHdwe2016Nw.Ini in tne Score2016NW Directory section SQL
CntStr := 'Provider='+ReadIniStr(IniHdwe,'SQL','Provider')+';';//SQLNCLI11.1';//SQLNCLI10.1;';
CntStr := CntStr + 'Integrated Security='+ReadIniStr(IniHdwe,'SQL','Integrated Security')+';';//"";';
CntStr := CntStr + 'Persist Security Info='+ReadIniStr(IniHdwe,'SQL','Persist Security Info')+';';//False;';
CntStr := CntStr + 'User ID='+ReadIniStr(IniHdwe,'SQL','User ID')+';';//shithead;';
CntStr := CntStr + 'password='+ReadIniStr(IniHdwe,'SQL','password')+';';//shithead;';
CntStr := CntStr + 'OLE DB Services='+ReadIniStr(IniHdwe,'SQL','OLE DB Services')+';';// -2;';
CntStr := CntStr + 'Initial Catalog='+Catalog+';';
CntStr := CntStr + 'Data Source='+ReadIniStr(IniHdwe,'SQL','Data Source')+';';//\SQLEXPRESS;';
CntStr := CntStr + 'Initial File Name='+ReadIniStr(IniHdwe,'SQL','Initial File Name')+';';//"";';
CntStr := CntStr + 'Packet Size='+ReadIniStr(IniHdwe,'SQL','Packet Size')+';';//4096;';
CntStr := CntStr + 'Auto Translate='+ReadIniStr(IniHdwe,'SQL','Auto Translate')+';';//True;';
CntStr := CntStr + 'Server SPN='+ReadIniStr(IniHdwe,'SQL','Server SPN')+';';//""';
end;
// ShowMessage(CntStr);
DataBase.ConnectionString := CntStr;
try
DataBase.Connected := True;
if DataBase.Connected then
begin
// ShowMessage('After Conection');
result := True;
end
else
begin
result := False;
ShowMessage('Unable to Connect to Score2016Nw Database Bad Ip or Connection Missing1');
end;
except
result := False;
ShowMessage('Unable to Connect to Score2016Nw Database Bad Ip or Connection Missing2');
end;
end
else
result := True;
end
else
result := True; // we are still conected to the sql database
end;
My network person tells me that the fire fall port 1433 is open ( it is a hardware wirewall and I don't have access). I have checked and rechecked that on the subserver that the ip2 is Active = Yes; Enabled = Yes; IP Address = 255.255.255.0 (Sub net Mask); TCP Port = 1433 and IPALL Dynamic Ports = ''(Blank) and TCP Port = 1433. I have read just about every post I can find and nothing short of Installing SQL Server Express 2012 on the clients will make it work to talk to the subserver and connect to the database. Is there any tools I could use to find the problem or am I going to need to Install SQL Server on all clients (what a pain)
Your connection string includes SQLNCLI11 as its provider. This means, you need to install SQL Native Client 11 on this machine, as that's the provider it's looking for. When you install SQL Server, it also installs SQL Native Client for you by default. But on a machine which SQL has never been installed on, you will have to install it yourself.
Or, as an alternative, you could use the OLE DB drivers which come pre-installed in Windows, by using SQLOLEDB.1 for the provider instead.
So I've searched and found a lot of info in similar areas, but nothing that quite hits the issue I'm having.
I'm working in a test environment and need to restore from the same SQL database backup (.bak) to many named instances of SQL server. All the sql instances are pre-installed and running.
I played around with different ideas, but a batch file using sqlcmd seems to be the best suited for the job.
So I created a batch file (.bat) that asks for the starting and stopping instance numbers and then should restore from the backup to each SQL named instance incrementing the instance number along the way.
When it runs the sqlcmd appears to work fine. At the end it prints out
RESTORE DATABASE successfully processed X pages in Y seconds
Also the files (.mdf, .ndf, .ldf) are in the directory as expected and then it moves on to the next.
The problem is that when it moves on to the next, the files that were just restored disappear from the directory.
If anyone has any ideas it would certainly be appreciated.
Here's the batch...
ECHO OFF
ECHO Enter starting instance number for restore db
SET /P _IntStart=
ECHO Enter number of last instance for restore db
SET /P _IntStop=
SET /a _IntStop=_IntStop+1
:RestoreDb
If %_IntStart% GEQ %_IntStop% goto:EOF
ECHO Display Instance Number... IntStart = %_IntStart%
sqlcmd -e -s localhost\instance%_IntStart% -d master -U user -P password -Q "Use [master]; RESTORE DATABASE DBName1 FROM DISK = 'C:\DBName1.bak'WITH REPLACE, MOVE 'DBName1' TO 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE%_IntStart%\MSSQL\DATA\DBName1.mdf', MOVE 'DBName1_log' TO 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE%_IntStart%\MSSQL\DATA\DBName1_log.LDF', MOVE 'ftrow_DBName1Catalog' TO 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE%_IntStart%\MSSQL\DATA\DBName1_1.ndf';"
SET /a _IntStart=_IntStart+1
GOTO:RestoreDb
PAUSE
EXIT
=========================================
From SQL Mgmt. Studio I've also tried the below. It works if I comment out the loop and run it each time manually bumping the instance number. It will create separate copies of the db and files. The problem here is SQLCMD doesn't appear to like concatenation in Mgmt. Studio so I can't increment the instance number in the :CONNECT. It ends up trying to connect to localhost\instance$(SCintnum).
Declare #intnum int
Set #intnum = 1
Declare #intstr NVARCHAR(255)
Set #intstr = #intnum
Declare #PathName1 NVARCHAR(255)
Declare #PathName2 NVARCHAR(255)
Declare #PathName3 NVARCHAR(255)
Set #PathName1 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1.mdf'
Set #PathName2 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1_log.LDF'
Set #PathName3 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1_1.ndf'
While #intnum < 51
:SETVAR SCintnum 1
:CONNECT localhost\instance$(SCintnum) -U user -P password
Use [master];
RESTORE DATABASE DBName1 FROM DISK = 'C:\DBName1.bak'
WITH REPLACE,
MOVE 'DBName1' TO #PathName1,
MOVE 'DBName1_log' TO #PathName2,
MOVE 'ftrow_DBName1Catalog' TO #PathName3;
:SETVAR SCintnum $(SCintum)+1
Set #intnum = #intnum+1
Set #intstr = #intnum
Set #PathName1 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1.mdf'
Set #PathName2 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1_log.LDF'
Set #PathName3 = 'E:\Microsoft SQL Server\MSSQL10_50.INSTANCE' + #intstr + '\MSSQL\DATA\DBName1_1.ndf'
===================================================================
This is an example of what I ended up using in c#.....
///Set SQL Connection
SqlConnection myConnection = new SqlConnection("user id=sa;" +
"password="+ sapassword+";server="+servername+"\\instance"+currentinstancenum+";" +
"Trusted_Connection=yes;" +
"database=master; " +
"connection LifeTime=0; connection Timeout=30");
///Set SQL Command
string thesqlcommand = "USE [master]; RESTORE DATABASE " + dbname + " FROM DISK = '" + backuplocation + "' WITH REPLACE, MOVE '" + dbname + "' TO " + #PathName1 + ", MOVE '" + dbname + "_log' TO " + #PathName2 + ", MOVE 'ftrow_" + dbname + "Catalog' TO " + #PathName3 + ";";
SqlCommand myCommand = new SqlCommand(thesqlcommand, myConnection);
///Set SQL Command TimeOut, open connection, execute command, close command
myCommand.CommandTimeout = 180;
myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myConnection.Close();
It is doing what you asked...
MOVE 'DBName1'
and
MOVE 'DBName1_log'
Ended up creating a little utility in C# to do this. Wish I had started there as it was far simpler. I added an example to the bottom of the original post.