Visual Studio 2010 Database Builds Drop If Exists - visual-studio-2010

Is there any way i can change the "Alter" statements for tables and procs to "Drop if exists" when the build spits out the scripts??
Using Visual Studio 2010 Ultimate. TFS 2010.

I believe the code you are referring to is generated from a template.
Look here...
C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\Templates\Database Project Items
and the modify these two files.
New Table Script.sql
New Stored Procedure Script.sql

After the procedure has been created for the first time what you will see is the code the tool gets/reads from the database, no longer an script that you could edit; of course you could copy/paste whatever it shows you into a text editor and save it as an SQL file (.sql extension).
If you try this sample code
IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'usp_test_proc')
BEGIN
DROP Procedure usp_test_proc
END
ALTER PROCEDURE dbo.usp_test_proc
/*
(
#parameter1 int = 5,
#parameter2 datatype OUTPUT
)
*/
AS
/* SET NOCOUNT ON */
select name, comment from test_table
RETURN
you will get this message:
"Unable to save object because the statement type is not supported. It must begin with CREATE or ALTER."
I suggest you create your own SQL procedure files and add the exists statment at the top, for example:
IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'usp_test_proc')
BEGIN
DROP Procedure usp_test_proc
END
CREATE PROCEDURE usp_test_proc
/*
(
#parameter1 int = 5,
#parameter2 datatype OUTPUT
)
*/
AS
/* SET NOCOUNT ON */
select name, comment from test_table
RETURN
That way you can edit/change your SQL code file at your convenience then just recreate the procedure connecting to your database by opening a new query connection through the Visual Studio menu 'Data/Transact-SQL Editor/New Query Connection', opening the SQL file and clicking on the Execute SQL toolbar button (green arrow).

Related

Running PL/SQL script in PHP

I have a script in PL/SQL , that drop some tables , sequences , triggers, and creating them again in the same script , I need this script in my website for deleting all data from database (and I want to acces this script pressing one button on website) so I tried to do a function / procedure in PL/SQL that read line by line from the script file and executing every line with dynamic sql , everything went ok till one error at:
CREATE OR REPLACE TRIGGER players_bir BEFORE INSERT ON players FOR EACH ROW BEGIN SELECT players_seq.NEXTVAL INTO :new.id FROM dual END
this gave me the error:
ORA-24344: success with compilation error
I searched for solutions, but I didn't find anything.
You are missing the semi-colon after dual on your SELECT statement. This ORA error generally means you compiled some code, but that is has some issue.
CREATE OR REPLACE TRIGGER players_bir
BEFORE INSERT ON players
FOR EACH ROW
BEGIN
SELECT players_seq.nextval
INTO :new.id
FROM dual;
END
Looking in all_errors will show you what the issue is or you could manually compile this trigger in some IDE (like SQL Developer) and that should also make it obvious.
SELECT *
FROM all_errors e
WHERE e.name = 'PLAYERS_BIR'
AND e.type = 'TRIGGER';
Additionally if all you are using your trigger for is to set some identity column and you are on Oracle 12c you can use some of the new features to accomplish this. Triggers are inherently slow and the new identity feature performs about as good as referencing the sequence directly in your INSERT.

Using temporary tables in ssis package

i have a problem - I want to use temp table in stored procedure is SQL Server, which will be executed from SSIS package.
I read some tips how to do it and I tried this one (first answer): Using Temp tables in SSIS
but it didn't work.
I have MS Visual Studio 2010, couldn't be problem with this version?
Here is my code in stored proc.:
CREATE PROCEDURE some_procedure
AS
SET NOCOUNT ON
IF 1 = 0
BEGIN
SELECT CAST(NULL AS int) as number
END
CREATE TABLE #some_table (number int)
INSERT INTO #some_table VALUES (250)
SELECT number FROM #some_table
Thanks for any advice or experience.
Here is error message from Visual Studio:
Error at Data Flow Task [OLE DB Source [1]]: SSIS Error Code
DTS_E_OLEDBERROR. An OLE DB error has occurred. Error code:
0x80004005. An OLE DB record is available. Source: "Microsoft SQL
Server Native Client 11.0" Hresult: 0x80004005 Description: "The
metadata could not be determined because statement 'INSERT INTO
#some_table VALUES (250)' in procedure 'some_procedure' uses a temp table.".
Error at Data Flow Task [OLE DB Source [1]]: Unable to retrieve column
information from the data source. Make sure your target table in the
database is available.
In SQL Server 2012 if you use temporary tables you must specify a results set.
This is an issue with the sp_describe_first_result_set procedure that SSIS uses to returns the output metadata.
E.g.
EXEC dbo.RptResults_StoredProcedure
Becomes
EXEC dbo.RptResults_StoredProcedure
WITH RESULT SETS
((
Date NVARCHAR(10),
Location VARCHAR(12),
Department CHAR(1),
Shift CHAR(1),
ForecastSales DECIMAL(18,2),
ActualSales DECIMAL(18,2)
))
For more information view
http://blog.concentra.co.uk/2014/08/22/column-metadata-determined-correctly-ssis-data-flow-task-stored-procedure-inputs/
Instead of temp table you can use table variable or cte... these don't have the issue like temp table.
CREATE PROCEDURE some_procedure
AS
SET NOCOUNT ON
Declare #some_table TABLE (number int)
INSERT INTO #some_table VALUES (250)
SELECT number FROM #some_table

How to get a stored procedure scalar output and add it to each row in the pipeline?

I am working on an SSIS package to transfer data from an ERP system (Microsoft Dynamics AX) to a custom CRM solution. One of the things I need to transfer/update is customers. In the CRM system, there is a field called CustomerID that is unique to the CRM environment and must be set when the data is transferred from the ERP system to the CRM system.
The issue is that I must call a stored procedure to get the CustomerID for the next customer to be inserted. How can I do this from within SSIS? I am currently using a Data Flow to transfer data and the only place I can see to called the stored procedure is from within the ADO NET Source task as a SQL Command query and each time the procedure is called it increments the ID so every time the SSIS package is run it updates the CustomerID field for all customers in the CRM database.
The stored procedure resides on the custom CRM application. The stored procedure does not accept any input parameters. It simply outputs a scalar value like CT000001, CT000002, etc. every time it is called.
What are my other options for doing this properly?
You need to call the stored procedure for each row using Script Component and add the value to the pipeline downstream to the destination.
Sample SSIS 2012 package that illustrates a sample:
The sample uses the following database objects.
SQL Server 2012 database named PracticeDB. In this scenario both the CRM and ERP tables are in the same database to keep it simple.
Table dbo.CRM will contain the destination CRM data.
Table dbo.ERP holds the source ERP data
Table dbo.CustomerId is a hypothetical table that is in CRM system which will be used to increment the customer number.
Stored procedure dbo.GetCustomerId increments the customer number whenever it is called.
Script to create the above mentioned database objects:
Below script will create the above mentioned objects and will insert some rows into the source ERP table.
USE PracticeDB;
GO
CREATE TABLE dbo.CRM(
CRMId int IDENTITY(1,1) NOT NULL,
CustomerId int NOT NULL,
CustomerName varchar(50) NULL
);
GO
CREATE TABLE dbo.ERP(
ERPId int IDENTITY(1,1) NOT NULL,
CustomerName varchar(50) NOT NULL
);
GO
CREATE TABLE dbo.CustomerId(
Id int NOT NULL
);
GO
CREATE PROCEDURE dbo.GetCustomerId
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS(SELECT Id FROM dbo.CustomerId)
INSERT INTO dbo.CustomerId (Id) VALUES(1);
ELSE
INSERT INTO dbo.CustomerId (Id)
SELECT MAX(Id) + 1 FROM dbo.CustomerId;
SELECT MAX(Id) AS CustomerId FROM dbo.CustomerId;
END;
GO
INSERT INTO dbo.ERP (CustomerName) VALUES
('John Doe')
, ('Jane Doe')
, ('Stephen Smith')
, ('Dean Jones')
;
GO
Create an SSIS package and create an ADO.NET connection manager to connect to the appropriate data sources.
Drag and drop a Data Flow Task onto the Control Flow tab
Within the data flow task, drag and drop the components ADO.NET Source, Script Component (Transformation) and ADO.NET Destination.
ADO.NET Source will read data from table dbo.ERP
ADO.NET Destination will insert data into table dbo.CRM
Script Component will involve the following configuration.
Double-click the Script Component to open the Script Component Editor.
Click Connection Managers tab page
Select the ADO.NET Connection Manager ADONET_PracticeDB and give it a name like PracticeDB. This connection manager will be used inside the script component code.
Click Inputs and Outputs tab page
Rename Input to ERP and Output to CRM
Expand CRM, select Output Columns and click Add Column.
Rename the column name to CustomerID. The example uses the column of type integer. You need to change the data type according to your needs.
Click Script tab page.
On the script tab page, click Edit Script....
Type the code shown in the below script component section. The script initiates the connection using the ADO.NET Connection Manager available on the package and then initiates the command object within the PreExecute method.
The stored procedure is then called within the ERP_ProcessInputRow method for every row in the pipeline to generate new customer ids.
Script component code in C#
#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Data.OleDb;
using System.Data.SqlClient;
#endregion
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
IDTSConnectionManager100 manager;
SqlConnection connection = null;
SqlCommand command = null;
public override void PreExecute()
{
manager = base.Connections.PracticeDB;
connection = new SqlConnection();
connection = (SqlConnection)manager.AcquireConnection(null);
command = new SqlCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.GetCustomerId";
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public override void ERP_ProcessInputRow(ERPBuffer Row)
{
Row.CustomerID = Convert.ToInt32(command.ExecuteScalar());
}
}
Close the Script component
Executed the below query against data to check the rows before executing the package.
Table select queries:
SELECT * FROM dbo.ERP;
SELECT * FROM dbo.CRM;
SELECT * FROM dbo.CustomerId;
After first execution of the package, you can notice that 4 rows have been inserted and also the stored procedure was successfully called to add the customer Ids.
After second execution of the package, you can notice that 4 more rows have been inserted and the stored procedure has successfully incremented the customer Ids.
Hope that gives you an idea.

Error SQL03120 on Trigger scripts in 2008 DB Project

I'm working on adding a database project in VS2010. I created a SQL 2008 DB Project, pointed at the development server, and it seems to have generated all of the appropriate schema objects. However, all of the CREATE TRIGGER scripts have the following error:
SQL03120: Cannot find element referenced by the supporting statement
Googling that error message doesn't return much, and seems to point to scripts using ALTER instead of CREATE which isn't the case here. This is an example of one of the scripts:
CREATE TRIGGER [TR_t_TABLE_TRIGGERNAME] ON [content].[t_TABLE]
FOR INSERT
AS
BEGIN
IF ( SELECT COUNT(*) FROM inserted) > 0
BEGIN
DECLARE #columnBits VARBINARY(50)
SELECT #columnBits = COLUMNS_UPDATED() | CAST (0 AS BIGINT)
INSERT INTO [history].[t_TABLE]
(
....
)
SELECT
....
FROM inserted
END
END
GO
EXECUTE sp_settriggerorder #triggername = N'[Content].[TR_t_TABLE_TRIGGER]', #order = N'last', #stmttype = N'insert';
The line that Visual Studio is attributing the error to is the last line executing the system proc. What stands out to me is that none of the object exist in the dbo schema. The table is in the Content schema and it has a matching table in the History schema. It would seem like the [Content] and [History] qualifiers would be resolvable though. Can't figure this one out...
Since this post comes up when you search for the above error on Google: another reason for this error is if you've got a stored procedure in a database project which specifies ALTER PROCEDURE rather than CREATE PROCEDURE.

Is it possible to inspect the contents of a Table Value Parameter via the debugger?

Does anyone know if it is possible to use the Visual Studio / SQL Server Management Studio debugger to inspect the contents of a Table Value Parameter passed to a stored procedure?
To give a trivial example:
CREATE TYPE [dbo].[ControllerId] AS TABLE(
[id] [nvarchar](max) NOT NULL
)
GO
CREATE PROCEDURE [dbo].[test]
#controllerData [dbo].[ControllerId] READONLY
AS
BEGIN
SELECT COUNT(*) FROM #controllerData;
END
DECLARE #SampleData as [dbo].[ControllerId];
INSERT INTO #SampleData ([id]) VALUES ('test'), ('test2');
exec [dbo].[test] #SampleData;
Using the above with a break point on the exec statement, I am able to step into the stored procedure without any trouble. The debugger shows that the #controllerData local has a value of '(table)' but I have not found any tool that would allow me to actual view the rows that make up that table.
Since you get no joy from the debugger, here is my suggestion. You add an input varaiable to determine if it is in test mode or not. Then if it is in testmode, run the select at the top of the sp to see what the data is.
CREATE TYPE [dbo].[ControllerId] AS TABLE(
[id] [nvarchar](max) NOT NULL
)
GO
CREATE PROCEDURE [dbo].[jjtest]
(#controllerData [dbo].[ControllerId] READONLY
, #test bit = null)
AS
IF #test = 1
BEGIN
SELECT * FROM #controllerData
END
BEGIN
SELECT COUNT(*) FROM #controllerData;
END
GO
DECLARE #SampleData as [dbo].[ControllerId];
INSERT INTO #SampleData ([id]) VALUES ('test'), ('test2');
EXEC [dbo].[jjtest] #SampleData, 1;
I got no success trying to do the same what you described. So I guess it isn't possible yet. Will wait for SSMS 2010
It is not possible for table variables, but I built a procedure which will display the content of a temp table from another database connection. (which is not possible with normal queries).
Note that it uses DBCC PAGE & the default trace to access the data so only use it for debugging purposes.
You can use it by putting a breakpoint in your code, opening a second connection and calling:
exec sp_select 'tempdb..#mytable'
There is a solution I think you can create another stored procedure and fill the table value parameter and the call your main procedure and then you start debugging from the test procedure you made.

Resources