A file activation error occurred. The physical file name 'N#filename - sql

Below t-sql code compiles fine. But when I run it like
exec [SP_ATTACH_NW] N'C:\myfolder' I get
Msg 5105, Level 16, State 2, Procedure SP_ATTACH_NW, Line 14
A file activation error occurred. The physical file name 'N#mdfFileName' may be incorrect. Diagnose and correct additional errors, and retry the operation.
USE master
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[SP_ATTACH_NW] (
#DestFolder varchar(255)
)
AS
BEGIN
SET NOCOUNT ON;
Declare #mdfFileName varchar(255)
Declare #ldfFileName varchar(255)
set #mdfFileName = #DestFolder + '\northwnd.mdf'
set #ldfFileName = #DestFolder + '\northwnd.ldf'
CREATE DATABASE [Northwind] ON
( FILENAME = N#mdfFileName ),
( FILENAME = N#ldfFileName )
FOR ATTACH
END
Pls advise. thanks

You can't have variables in the filename arguments of CREATE DATABASE (MSDN doesn't show #vars in the syntax)
The code above is literally looking for the constant "N#mdfFileName" as a filename.
You'd need dynamic SQL to build a string in, say, #MyBuiltSQL then run EXEC(#MyBuiltSQL)
Note: The "N" prefix here would not make #mdfFileName nvarchar anyway

Related

How to solve this SQL Server error I'm getting?

As you can see below I am trying to execute a stored procedure by passing the two parameters, I get error like
Msg 102, Level 15, State 1, Line 19
Incorrect syntax near 'C:\SQL_Backup\Test.bak'.
Code:
EXEC Proc_RestoreSQL_Database ('C:\SQL_Backup\Test.bak','DMTest')
Stored procedure being executed:
ALTER PROCEDURE [dbo].[Proc_RestoreSQL_Database]
#DISK nvarchar(1000),
#DBName varchar(1000)
AS
BEGIN
-- Create DB with script(DMUtilityTest)
CREATE DATABASE [#DBName]
-- restore
RESTORE DATABASE [#DBName]
FROM DISK = N'#DISK'
END
There is no need to CREATE the database if you are immediately going to restore it.
Just execute the restore directly. Do not wrap the database name parameter in [], nor the filename parameter in quotes '', you only need this if you are embedding the actual name, not parameters.
You should also use more sensible parameter types
CREATE OR ALTER PROCEDURE [dbo].[Proc_RestoreSQL_Database]
#DISK nvarchar(255),
#DBName sysname
AS
RESTORE DATABASE #DBName
FROM DISK = #DISK;
GO
This obviously assumes you are going to restore to the same location. You may want to pass new locations using MOVE TO #newFile
To execute it, again do not wrap in parenthesis (), just specify the parameter names
EXEC Proc_RestoreSQL_Database #DISK = 'C:\SQL_Backup\Test.bak', #DBName = 'DMTest';

SQL Scripted Restore Using With Move - With File & With

I am trying to script a restore of one of our databases and I need to know the correct syntax for using the with file and with move commands
So far I have:
RESTORE DATABASE Test
FROM DISK = 'E:\Test_db_BASELINE.BAK'
WITH FILE = 1
WITH MOVE 'Test_dat' TO 'C:\MSSQL\v2_Data\Test_Data.MDF',
MOVE 'Test_log' TO 'C:\MSSQL\v2_Data\Test_Log.LDF', REPLACE
I get syntax error any ideas?
to put into context I am trying to execute the below to automate a restore where the bak file has a timestamped naming convention:
--==CHECK IF DB EXISTS IF IT DOES DROP IT
USE [master]
IF EXISTS(SELECT * FROM sys.databases where name='SlotLookup')
DROP DATABASE [SlotLookup]
--==START THE RESTORE PROCESS
DECLARE #FileName varchar(255), #PathToBackup varchar(255), #RestoreFilePath varchar(1000)
DECLARE #Files TABLE (subdirectory varchar(255), depth int, [file] int)
SET NOCOUNT ON
--==SET THE FILEPATH
SET #PathToBackup = 'path'
--insert into our memory table using dirtree and a single file level
INSERT INTO #Files
EXEC master.dbo.xp_DirTree #PathToBackup,1,1
SELECT TOP 1
#FileName = [subdirectory]
FROM
#Files
WHERE
-- get where it is a file
[file] = 1
AND
--==FIND THE LOGICAL NAME OF THE BAK FILE FROM THE CHRONILOGICALLY ORDERED LIST
subdirectory LIKE '%.bak'
ORDER BY
-- order descending so newest file will be first by naming convention
subdirectory DESC
IF LEFT(REVERSE(#PathToBackup), 1) != '\'
BEGIN
SET #PathToBackup = #PathToBackup + '\'
END
SET #RestoreFilePath = #PathToBackup + #FileName
SELECT #RestoreFilePath
--===BEGIN THE RESTORE TO THE DESIGNATED SERVER
RESTORE DATABASE [SlotLookup]
FROM DISK = #RestoreFilePath
FILE = 1
WITH MOVE 'SlotLookup' TO 'path\SlotLookup.mdf',
MOVE 'SlotLookup_log' TO 'path\SlotLookup_log.ldf'
get syntax error
Msg 156, Level 15, State 1, Line 48
Incorrect syntax near the keyword 'FILE'.
Msg 319, Level 15, State 1, Line 49
The syntax of a restore backup script with move is like this following:
RESTORE DATABASE [AdventureWorksCopy] FROM DISK = 'c:\mssql\backup\[...]\Backup.bak'
WITH CHECKSUM,
MOVE 'AdventureWorks_Data' TO 'c:\mssql\data\[...]\AdventureWorksCopy_Data.mdf',
MOVE 'AdventureWorks_Log' TO 'c:\mssql\log\[...]\AdventureWorksCopy_Log.ldf',
RECOVERY, REPLACE, STATS = 10;
What syntax error do you get?
Please include it in the questions

How to add code to initialize sql database

I use codefirst and I use Elmah.
I recreated every time the database, you must manually add the code from the file:
/*
ELMAH - Error Logging Modules and Handlers for ASP.NET
Copyright (c) 2004-9 Atif Aziz. All rights reserved.
Author(s):
Atif Aziz, http://www.raboof.com
Phil Haacked, http://haacked.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
-- ELMAH DDL script for Microsoft SQL Server 2000 or later.
-- $Id: SQLServer.sql 677 2009-09-29 18:02:39Z azizatif $
DECLARE #DBCompatibilityLevel INT
DECLARE #DBCompatibilityLevelMajor INT
DECLARE #DBCompatibilityLevelMinor INT
SELECT
#DBCompatibilityLevel = cmptlevel
FROM
master.dbo.sysdatabases
WHERE
name = DB_NAME()
IF #DBCompatibilityLevel <> 80
BEGIN
SELECT #DBCompatibilityLevelMajor = #DBCompatibilityLevel / 10,
#DBCompatibilityLevelMinor = #DBCompatibilityLevel % 10
PRINT N'
===========================================================================
WARNING!
---------------------------------------------------------------------------
This script is designed for Microsoft SQL Server 2000 (8.0) but your
database is set up for compatibility with version '
+ CAST(#DBCompatibilityLevelMajor AS NVARCHAR(80))
+ N'.'
+ CAST(#DBCompatibilityLevelMinor AS NVARCHAR(80))
+ N'. Although
the script should work with later versions of Microsoft SQL Server,
you can ensure compatibility by executing the following statement:
ALTER DATABASE ['
+ DB_NAME()
+ N']
SET COMPATIBILITY_LEVEL = 80
If you are hosting ELMAH in the same database as your application
database and do not wish to change the compatibility option then you
should create a separate database to host ELMAH where you can set the
compatibility level more freely.
If you continue with the current setup, please report any compatibility
issues you encounter over at:
http://code.google.com/p/elmah/issues/list
===========================================================================
'
END
GO
/* ------------------------------------------------------------------------
TABLES
------------------------------------------------------------------------ */
CREATE TABLE [dbo].[ELMAH_Error]
(
[ErrorId] UNIQUEIDENTIFIER NOT NULL,
[Application] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Host] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Type] NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Source] NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Message] NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[User] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[StatusCode] INT NOT NULL,
[TimeUtc] DATETIME NOT NULL,
[Sequence] INT IDENTITY (1, 1) NOT NULL,
[AllXml] NTEXT COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
)
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[ELMAH_Error] WITH NOCHECK ADD
CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY NONCLUSTERED ([ErrorId]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ELMAH_Error] ADD
CONSTRAINT [DF_ELMAH_Error_ErrorId] DEFAULT (NEWID()) FOR [ErrorId]
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_App_Time_Seq] ON [dbo].[ELMAH_Error]
(
[Application] ASC,
[TimeUtc] DESC,
[Sequence] DESC
)
ON [PRIMARY]
GO
/* ------------------------------------------------------------------------
STORED PROCEDURES
------------------------------------------------------------------------ */
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_GetErrorXml]
(
#Application NVARCHAR(60),
#ErrorId UNIQUEIDENTIFIER
)
AS
SET NOCOUNT ON
SELECT
[AllXml]
FROM
[ELMAH_Error]
WHERE
[ErrorId] = #ErrorId
AND
[Application] = #Application
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_GetErrorsXml]
(
#Application NVARCHAR(60),
#PageIndex INT = 0,
#PageSize INT = 15,
#TotalCount INT OUTPUT
)
AS
SET NOCOUNT ON
DECLARE #FirstTimeUTC DATETIME
DECLARE #FirstSequence INT
DECLARE #StartRow INT
DECLARE #StartRowIndex INT
SELECT
#TotalCount = COUNT(1)
FROM
[ELMAH_Error]
WHERE
[Application] = #Application
-- Get the ID of the first error for the requested page
SET #StartRowIndex = #PageIndex * #PageSize + 1
IF #StartRowIndex <= #TotalCount
BEGIN
SET ROWCOUNT #StartRowIndex
SELECT
#FirstTimeUTC = [TimeUtc],
#FirstSequence = [Sequence]
FROM
[ELMAH_Error]
WHERE
[Application] = #Application
ORDER BY
[TimeUtc] DESC,
[Sequence] DESC
END
ELSE
BEGIN
SET #PageSize = 0
END
-- Now set the row count to the requested page size and get
-- all records below it for the pertaining application.
SET ROWCOUNT #PageSize
SELECT
errorId = [ErrorId],
application = [Application],
host = [Host],
type = [Type],
source = [Source],
message = [Message],
[user] = [User],
statusCode = [StatusCode],
time = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z'
FROM
[ELMAH_Error] error
WHERE
[Application] = #Application
AND
[TimeUtc] <= #FirstTimeUTC
AND
[Sequence] <= #FirstSequence
ORDER BY
[TimeUtc] DESC,
[Sequence] DESC
FOR
XML AUTO
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
CREATE PROCEDURE [dbo].[ELMAH_LogError]
(
#ErrorId UNIQUEIDENTIFIER,
#Application NVARCHAR(60),
#Host NVARCHAR(30),
#Type NVARCHAR(100),
#Source NVARCHAR(60),
#Message NVARCHAR(500),
#User NVARCHAR(50),
#AllXml NTEXT,
#StatusCode INT,
#TimeUtc DATETIME
)
AS
SET NOCOUNT ON
INSERT
INTO
[ELMAH_Error]
(
[ErrorId],
[Application],
[Host],
[Type],
[Source],
[Message],
[User],
[AllXml],
[StatusCode],
[TimeUtc]
)
VALUES
(
#ErrorId,
#Application,
#Host,
#Type,
#Source,
#Message,
#User,
#AllXml,
#StatusCode,
#TimeUtc
)
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
I execute this code automatically?
I tried to use db.Database.ExecuteSqlCommand but I get lots of errors of the form:
Incorrect syntax near 'GO'.
Incorrect syntax near the keyword 'ALTER'.
Incorrect syntax near the keyword 'ALTER'.
Incorrect syntax near 'GO'.
Incorrect syntax near the keyword 'SET'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Must declare the scalar variable "#ErrorId".
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Must declare the scalar variable "#TotalCount".
Must declare the scalar variable "#PageIndex".
Must declare the scalar variable "#TotalCount".
Must declare the scalar variable "#Application".
Must declare the scalar variable "#PageSize".
Must declare the scalar variable "#PageSize".
Must declare the scalar variable "#Application".
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Must declare the scalar variable "#ErrorId".
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
Try this migration, bearing in mind that it expects all GO statements to be on a single line and that the file uses \r\n line endings. I installed Elmah using the elmah.sqlserver NuGet package, which drops the SqlServer.sql file in the appropriate location. You will need to change the resource name to match your project.
public partial class Elmah : DbMigration
{
public override void Up()
{
var sqlStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyProject.App_Readme.Elmah.SqlServer.sql");
using(var sqlStreamReader = new StreamReader(sqlStream))
{
string sqlScript = sqlStreamReader.ReadToEnd();
ExecuteSqlScript(sqlScript);
}
}
void ExecuteSqlScript(string sqlScript)
{
string[] sql = sqlScript.Split(new[] {"\r\nGO\r\n"}, StringSplitOptions.RemoveEmptyEntries);
foreach (var sqlCommand in sql)
{
if (!string.IsNullOrWhiteSpace(sqlCommand))
Sql(sqlCommand);
}
}
public override void Down()
{
DropTable("ELMAH_Error");
Sql("DROP PROCEDURE ELMAH_GetErrorXml");
Sql("DROP PROCEDURE ELMAH_GetErrorsXml");
Sql("DROP PROCEDURE ELMAH_LogError");
}
}
I
just to formalize my comment to the OP as an answer;
I think that the best practice here would be that only your code-first db should be affected by any radical changes (i.e. recreation of the db on the model changing). All other tables unrelated to that should be in an ApplicationServices db or similar and NOT in the core db. That way you don't create a support nightmare everytime you need to update your model with a simple property or data type change. Plus, you do of course end up losing the entire history of your logging (and other) db tables every time you make a change.
So, in a word, I think you're tackling the wrong problem with a potentially inappropriate solution.
This is certainly how we do it in our shop and in previous projects that I've worked on.
This is a series of SQL commands separated by GO statements (which aren't strictly T-SQL commands)
You can use SQL Managment Studio to execute the script, or the command line tool SQLCMD.exe
I don't think you should run that many batches on ExecuteSqlCommand.
Why don't you simply execute it on SSMS?
You'll need to parse your script, split it to separate SQL commands and execute each one of them individually through SqlCommand. Unfortunately, I'm not aware of a way to automate this.
The script requires you to separate the batches (GO is the batch separator) and send each batch individually to SQL Server. I actually have a sample project dbutilsqlcmd that does just that, and also supports more of the sqlcmd extensions like :setvar and $(variable) replacement in the script, which can be quite useful at deployment.
There is now a nuget package that will initialize the Elmah table and procs for you: https://www.nuget.org/packages/Elmah.SqlServer.EFInitializer/. Add it to your web project. It will then use EF code first to create it for you. It adds an Initializer to your App_Start folder so you actually don't have to add any code. It will add a migration to your database to ensure it only gets added once.

How can I create a database and USE statements in one script?

Consider the following script:
DECLARE #path varchar(MAX)
DECLARE #script varchar(MAX)
SET #path = (SELECT physical_name FROM sys.master_files where name = 'master');
SET #path = REPLACE(#path, 'master.mdf', '');
SELECT #path;
SET #script =
'CREATE DATABASE test
ON PRIMARY
(NAME = test_primary,
FILENAME = ''' + #path + 'test_primary.mdf'',
SIZE = 10MB,
FILEGROWTH = 10MB)';
exec(#script);
USE test
When I try to run it all at once I get an error:
Msg 911, Level 16, State 1, Line 31
Database 'test' does not exist. Make sure that the name is entered correctly.
If I first run exec and then separately run USE it all goes fine.
The question is, how can I work-around it, so that it'd be possible to run the whole script at once with no errors?
SQL Server compiles the code for one batch at a time. When your code is compiled the database does not exist.
Add a batch separator before use test.
DECLARE #path varchar(MAX)
DECLARE #script varchar(MAX)
SET #path = (SELECT physical_name FROM sys.master_files where name = 'master');
SET #path = REPLACE(#path, 'master.mdf', '');
SELECT #path;
SET #script =
'CREATE DATABASE test
ON PRIMARY
(NAME = test_primary,
FILENAME = ''' + #path + 'test_primary.mdf'',
SIZE = 10MB,
FILEGROWTH = 10MB)';
exec(#script);
GO
USE test
If you are executing the statements from within one of the SQL Server query tools (e.g. enterprise manager, management studio or sqlcmd), then insert the statement GO prior to the USE test command. This separates the commands into separate batches. If you are executing the script through one of the programmatic clients, then you must execute the batches separately by splitting up the script.
Souldn't USE be at the top of the script?
USE selects the correct database for you. Then run the script on that database

Execute stored proc with OPENQUERY

I have SQL Server 2008 with a linked Sybase server and I am trying to execute a stored procedure on the Sybase server using OPENQUERY. If I have a stored proc that doesn't take parameters it succeeds fine. If I have a stored proc with parameters it fails. I even tried a very basic stored proc that only took an int an that still failed. Below is the syntax I am using:
select * from
OPENQUERY([LINKSERVER],'exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
Msg 7357, Level 16, State 2, Line 3
Cannot process the object "exec database.user.my_stored_proc 'AT','XXXX%','1111',1". The OLE DB provider "ASEOLEDB" for linked server "LINKSERVER" indicates that either the object has no columns or the current user does not have permissions on that object.
As the proc will execute just fine without parameters, I don't think it is a permission issue.
This worked for me,
SELECT * FROM OPENQUERY(LOCALSERVER, 'SET FMTONLY OFF EXEC snr.dbo.GetAllSignals #controlRunId = 25, #experimentRunId = 26')
I was creating temporary tables, and that's why i got access denied
Here is more info http://www.sommarskog.se/share_data.html#OPENQUERY
I create a sp that doesn't return any value and it doesn't work.
Your SP in mysql have to return a value!
for example I do this in "mysql":
CREATE DEFINER=`root`#`localhost` PROCEDURE `MyPro`(IN `Name` VARCHAR(50), IN `Id` INT, OUT `Result` INT)
MODIFIES SQL DATA
BEGIN
DECLARE Result INT;
SET Result = 0;
INSERT into MyTable (Id,Name) VALUES(Id,Name);
SELECT Result;
END
That "Id" and "Name" is input parameter and "Result" is output parameter
and create linked server in SQL SERVER and call it like this:
select * from openquery
(
Test,'call mydb.MyPro(''Name'',''16'', #P0);'
)
It works for me :D
Linked Servers and OPENQUERY, Gems to MS SQL Server...that are wolves in sheep clothing. I've found the following solutions to work when dealing with parameters
If the SP is basically just SELECT statements, the move the same to a VIEW and just pass SQL statements via OPENQUERY.
Build the OPENQUERY as a string and then use execute_sql.
You could also see if it works to precede exec with SET FMTONLY ON:
OPENQUERY([LINKSERVER],'SET FMTONLY ON; exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
If you try this and it works, you should probably Google FMTONLY+OPENQUERY to get an idea of what it means.
Try this,
SELECT * FROM OPENQUERY(linked_server_name, 'SELECT postgres_procedure_name (parameters)');
I experienced a very similar issue, but my SP wasn't taking any parameters.
I tried experimenting with altering the query sent through the openquery to include 'SET NOCOUNT ON' and 'SET FMTONLY OFF' but this had no difference.
The only solution that worked for my stored procedure was dropping the existing version, and altering the code to specifically 'SET NOCOUNT ON'
After doing this I was able to successfully run my stored proc through my linked server connection.
First of all you have to add hard code text fields then you have to
replace it by your parameters value like FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType
DECLARE #startdate varchar(255) = '2019-12-17'
DECLARE #enddate varchar(255) = '2019-12-17'
Set #SQL = 'SELECT * FROM OPENQUERY(' + quotename(#LinkedServer) + ',' + '''' +
'SET FMTONLY OFF; exec [TAP].[dbo].[GetAttendanceList] ' + 'FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType,1'')'
You have to replace your parameters values shown below
set #SQL=REPLACE(#SQL,'FromDate',+''''+''''+#startdate+''''+'''')
set #SQL=REPLACE(#SQL,'TillDate',+''''+''''+#enddate+''''+'''')
set #SQL=REPLACE(#SQL,'CompCode',+''''+''''+#CompCode+''''+'''')
set #SQL=REPLACE(#SQL,'AtnType',+''''+''''+''''+'''')
if #EmpID is Null
begin
set #SQL=REPLACE(#SQL,'EmpID','null')
end
if #DeptID is Null
begin
set #SQL=REPLACE(#SQL,'DeptID','null')
end
if #DesgId is Null
begin
set #SQL=REPLACE(#SQL,'DesgId','null')
end
if #LocationID is Null
begin
set #SQL=REPLACE(#SQL,'LocationID','null')
end
print #SQL
exec ( #SQL)