Reuse t-sql table variable or clone its structure - sql-server

I'm writing stored procedure to paginate results of a different stored procedure. I do it by executing the stored procedure and inserting results into the table variable:
DECLARE #allResults table
(
[ID] [int] NOT NULL,
[DESCRIPTION] [varchar](MAX) NULL,
[COL1] [VARCHAR],
[COL2] [VARCHAR],
...
);
INSERT #allResults Exec [dbo].[GetResults];
I need to filter the results and store them somewhere because I will use filtered results in at least two places: to count all the records and to actually paginate. Ideally I'd like to reuse the #allResults table as I won't need its content anymore after filtering. Something similar to:
#allresults = #allresults where [DESCRIPTION] like '%keyword%'
I'm not exactly sure how can I truncate table in the same moment as I filter it. That's why I created second table variable with the same structure:
DECLARE #filteredResults table
(
[ID] [int] NOT NULL,
[DESCRIPTION] [varchar](MAX) NULL,
[COL1] [VARCHAR],
[COL2] [VARCHAR],
...
);
It's not a bad solution, and it works. But I wonder could I reuse the definition of a table variable? Something that would look like:
DECLARE #filteredResults, #allResults table
(
[ID] [int] NOT NULL,
[DESCRIPTION] [varchar](MAX) NULL,
[COL1] [VARCHAR],
[COL2] [VARCHAR],
...
);
Is there a way to do it? Maybe there's a way to clone table variable? I guess simultaneous delete and filtering could be achieved using delete with output clause but I'm not exactly sure how should I write it.
I hate to repeat code. Maybe there's a simple solution you know of :)

You can create your own user table type:
CREATE TYPE dbo._t_test AS TABLE(
[ID] [int] NOT NULL,
[DESCRIPTION] [varchar](MAX) NULL,
[COL1] [VARCHAR],
[COL2] [VARCHAR]
)
GO
And then create table variables like this:
DECLARE #filteredResults dbo._t_test
, #allResults dbo._t_test

Related

Inserting into a joined view SQL Server

This is a question more about design than about solving a problem.
I created three tables as such
CREATE TABLE [CapInvUser](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](150) NOT NULL,
[AreaId] [int] NULL,
[Account] [varchar](150) NULL,
[mail] [varchar](150) NULL,
[UserLevelId] [int] NOT NULL
)
CREATE TABLE [CapInvUserLevel](
[UserLevelId] [int] IDENTITY(1,1) NOT NULL,
[Level] [varchar](50) NOT NULL
)
CREATE TABLE [CapInvUserRegistry](
[UserRegistryId] [int] IDENTITY(1,1) NOT NULL,
[UserLevelId] int NOT NULL,
[DateRegistry] DATE NOT NULL,
[RegistryStatus] VARCHAR(50) NOT NULL,
)
With a view that shows all the data on the first table with "AreaId" being parsed as the varchar identifier of that table, the UserLevel being parsed as the varchar value of that table, and a join of the registry status of the last one.
Right now when I want to register a new user, I insert into all three tables using separate queries, but I feel like I should have a way to insert into all of them at the same time.
I thought about using a stored procedure to insert, but I still don't know if that would be apropiate.
My question is
"Is there a more apropiate way of doing this?"
"Is there a way to create a view that will let me insert over it? (without passing the int value manually)"
--This are just representations of the tables, not the real ones.
-- I'm still learning how to work with SQL Server properly.
Thank you for your answers and/or guidance.
The most common way of doing this, in my experience, is to write a stored procedure that does all three inserts in the necessary order to create the FK relationships.
This would be my unequivocal recommendation.

Get parameter values from DBCC INPUTBUFFER

I've created a trigger on a SQL Server 2012 table to log all INSERT, UPDATE and DELETE actions against the table to another table. I got my initial code from the blog post at http://sqlblog.com/blogs/jonathan_kehayias/archive/2010/01/11/tsql2sday-using-sys-dm-exec-sql-text-to-get-the-calling-statement.aspx.
Here are the scripts for a test table, the table I'm logging changes on the test table to, and the trigger on the test table:
CREATE TABLE [dbo].[TestAddresses](
[RecNo] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](50) NULL,
[LastName] [varchar](50) NULL,
[Address] [varchar](50) NULL,
[City] [varchar](50) NULL,
[State] [varchar](2) NULL,
[Zip] [varchar](12) NULL
) ON [PRIMARY]
GO
-------------------------------------
CREATE TABLE [dbo].[TestAddressesLog](
[RecNo] [int] IDENTITY(1,1) NOT NULL,
[Sql] [nvarchar](max) NULL,
[Timestamp] [datetime] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TestAddressesLog] ADD CONSTRAINT [DF_TestAddressesLog_Sql] DEFAULT (N'') FOR [Sql]
GO
ALTER TABLE [dbo].[TestAddressesLog] ADD CONSTRAINT [DF_TestAddressesLog_Timestamp] DEFAULT (getdate()) FOR [Timestamp]
GO
------------------------------------
ALTER TRIGGER [dbo].[TestAddressLogTrigger]
ON [dbo].[TestAddresses]
FOR INSERT, UPDATE, DELETE
AS
BEGIN
DECLARE #TEMP TABLE (EventType NVARCHAR(30), Parameters INT, EventInfo NVARCHAR(4000))
INSERT INTO #TEMP EXEC('DBCC INPUTBUFFER(##SPID)')
INSERT INTO TestAddressesLog (Sql)
SELECT EventInfo FROM #TEMP
END
This works great for standard CRUD operations where there are no parameters. However, when my .NET code executes a parameterized operation such as the following (assigning a value such as 'CA' to #NewState):
UPDATE TestAddresses SET State = #NewState WHERE State = 'TX'
I get the following result:
(#NewState int)UPDATE TestAddresses SET State = #NewState WHERE State = 'TX'
I need a way to get and record the value of the passed parameter. Anyone have a solution for this?
That's not going to work. The only way is to capture RPC Completed events using Extended Events, parse them and persist them.

In SQL Server, can I set a foreign key on a column that does not exist?

I am using SQL Server 2005, and I have 3 tables:
CREATE TABLE [dbo].[Workflow]
(
[WorkflowId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
[Description] [varchar](1000) NULL
)
CREATE TABLE [dbo].[Application]
(
[ApplicationId] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL
)
CREATE TABLE [dbo].[Rel_Workflow_Application]
(
[WorkflowId] [int] NOT NULL,
[ApplicationId] [int] NOT NULL
)
The rule is that in Rel_Workflow_Application, ApplicationId must exist in the Application table or it can be 0. I don't have a record in table Application where ApplicationId = 0 and I don't wish to create one.
How can I set this constraint?
Though it is possible to use the NOCHECK when creating a foreign key, this is a hack that might prove problematic. I would use null instead of 0 and if 0 needs to show up in queries use coalesce(ApplicationID, 0) in the select statements or create a view which does this and query that view instead.
This cleanly indicates that the foreign key does not have a row in Application.

Row update if row exists. Insert it if row doesn't exist

I'm developing a SQL SERVER 2012 express and developer solution.
I will receive an xml in an stored procedure. In the stored procedure I will parse the xml and insert its data into a table.
My problem here is that in this xml could contain data that exists on the table, and I need to update the data on the table with the new one.
I don't want to check if each row in xml exists on the table.
I think I can use IGNORE_DUP_KEY but I'm not sure.
How can I update or insert new data without checking it?
This is the table where I want to insert (or update) the new data:
CREATE TABLE [dbo].[CODES]
(
[ID_CODE] [bigint] IDENTITY(1,1) NOT NULL,
[CODE_LEVEL] [tinyint] NOT NULL,
[CODE] [nvarchar](20) NOT NULL,
[COMMISIONING_FLAG] [tinyint] NOT NULL,
[IS_TRANSMITTED] [bit] NOT NULL,
[TIMESPAN] [datetime] NULL,
[USERNAME] [nvarchar](50) NULL,
[SOURCE] [nvarchar](50) NULL,
[REASON] [nvarchar](200) NULL
CONSTRAINT [PK_CODES] PRIMARY KEY CLUSTERED
(
[CODE_LEVEL] ASC,
[CODE] ASC
)
)
The "IGNORE_DUP_KEY" parameter ,is ignore inserting new row, if he is already exists, but it is not dealing with update in case it exists.
the solution to your request is by MERGE or DML operation (INSERT/UPDATE/DELETE) .
BTW,
The parameter "IGNORE_DUP_KEY" is covering existsnce for the index key only (index column).

SQL Server - How to insert into Varbinary(Max) column?

I have a table that looks as follows below. I don't really want to create a C# application to insert rows into this table, if I can avoid it, because of the VarBinary column. My intent is to store a Crystal report .RPT file in this column. Is there a T-SQL statement I can execute to insert/update rows into this table, and include an .RPT file?
CREATE TABLE [Report].[MesReport](
[MesReportID] [int] IDENTITY(1,1) NOT NULL,
[ParentID] [int] NOT NULL,
[ReportTitle] [nvarchar](80) NOT NULL,
[ReportName] [nvarchar](80) NOT NULL,
[DatabaseServer] [nvarchar](80) NOT NULL,
[DatabaseName] [nvarchar](50) NOT NULL,
[Login] [nvarchar](80) NOT NULL,
[ReportFile] [varbinary](max) NULL,
You can get it into a variable like
DECLARE #VB varbinary(max)
SELECT #VB =BulkColumn FROM OPENROWSET(BULK
N'C:\YourReport.rpt', SINGLE_BLOB) AS Document
that you can then use in an insert statement

Resources