Advanced SQL Server stored procedure? - sql-server

I have one table in my database that I want to update each year. I need to pull two of the column values from my asp.net page and populate the rest from my database already.
I have a budget table for each year, the year updates automatically on my page according to the month of the year. When the month changes to a specific month I need the stored procedure to update itself to add the budget items with a blank amount so that I can enter the amounts manually.
Old Data:
Year Code1 Code1Description Code2 Code2Description BudgetAmt($750.00) Initials
New Data:
NewYear Code1 Code1Description Code2 Code2Description BudgetAmt($0.00) Initials
This so that when I enter editmode on my gridview the codes will already be there just with blank budgetamt for me to update. Does this make sense? Is it something that is possible?

You are having the webpage call the stored procedure? In which case simply create a table with the item codes you want to be populated:
ALTER PROCEDURE [dbo].[stp_TemplateSPROC]
(#year as int) AS
INSERT tbl_webpage (Year, code1, code1desc, code2, code2desc, spending, Initials)
Select
#Year [Year], code1, code1desc, code2, code2desc,
0 as spending, '' as Initials
from tablewithcodesin
This, when called, would populate a table with the Year, codes, and zeros/blanks for you to fill in.
tablewithcodesin would just be Code1 Code1Description Code2 Code2Description

Related

SQL Server : update trigger seeming to affect wrong column

Thanks for looking. I'm trying to write a SQL Server trigger that when a new record is added containing date information, will add the day of the week to the DayOfWeek column. Here's my table, with the columns in order:
Food table:
FoodName **varchar(20)**
CategoryID (FK) **int**
Price **smallmoney**
StoreID (FK) **int**
Date **datetime**
DayOfWeek **varchar(9)**
ShopperID (FK) **int**
Week **int**
Here is the trigger I've written:
-- Create a trigger to update day of the week when a record is inserted
CREATE TRIGGER DOW
ON Food
FOR INSERT
AS
BEGIN
-- Declare a variable to hold the date ID
DECLARE #dateID DATETIME
-- Get the date from the new record and store it in #dateID
SELECT #dateID = Date FROM Food
-- Insert day of the week based on the inserted date
INSERT INTO Food (DayOfWeek)
SELECT DATENAME(dw, #dateID)
END
GO
SQL Server seemed to accept the procedure, but when I ran another procedure to insert a new record, I got this error:
Msg 515, Level 16, State 2, Procedure DOW, Line 8 [Batch Start Line 21]
Cannot insert the value NULL into column 'Week', table *******; column does not allow nulls. INSERT fails.
I am not sure why this trigger is affecting the 'Week' column at all. The code should take the value entered for the Date and use the DATENAME(dw,...) function to return the day of the week, which should go into the DayOfWeek column. I've written a stored procedure that accepts a date as input and inserts the corresponding day of the week into the record, and it works just fine, but this trigger doesn't seem to want to cooperate. I'm stumped!
What your trigger does:
it fetches a Date from your table (the last one that is returned) which is not necessarily the last inserted value.
it tries to insert a new record with just the DayOfWeek of that Date specified.
it fails, because at least the Week must also be specified.
I guess that you want to update the value of the DayOfWeek for the inserted row(s) instead. To be able to do so, there must be a way to identify the row(s) that need to be updated in the Food table by knowing the values of the inserted rows. To be sure to update the correct rows, there should be a primary key that allows you to identify them. For sure you have such a primary key, and I guess that it's named FoodID, so probably you wanted to do this:
CREATE TRIGGER DOW ON Food
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
-- update the day of the week for the inserted rows
UPDATE Food
SET [DayOfWeek] = DATENAME(dw, f.[Date])
FROM Food f
INNER JOIN inserted i ON f.FoodID = i.FoodID
END
GO
There are some major problems with your trigger. In triggers, there is an inserted table (on inserts and updates) and deleted table (on deletes and updates). You should be using this table's information to know what records need updated.
This is bad because a trigger can have multiple rows
This SQL simply will not work correctly if you insert multiple rows.
DECLARE #dateID DATETIME
SELECT #dateID = Date FROM Food
This SQL is trying to insert a new row which is causing your NULL error
It is not trying to update the row you are inserting
INSERT INTO Food (DayOfWeek)
SELECT DATENAME(dw, #dateID)
It would need to be an INSTEAD OF trigger to avoid the null constraint on the column. Wolfgang's answer will still cause a null constraint error, because after triggers run AFTER the data is inserted. An INSTEAD OF trigger will run in place of the the actual insert.
CREATE TRIGGER DOW ON Food
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
-- update the day of the week for the inserted rows
INSERT INTO Food (FoodName,CategoryID,Price,StoreID,[Date],ShopperID,[Week],[DayOfWeek])
SELECT
FoodName,CategoryID,Price,StoreID,[Date],ShopperID,[Week],DATENAME(dw, [Date]) AS [DayOfWeek]
FROM inserted
END
GO
Personally, I think storing the week and day of week is a bad idea. You already have a value that can derive that information (Date). Any time you have multiple columns that are essentially duplicate data, you will run into maintenance pain.

How to select record for any date in given month

I have a table which is storing salary slip record along with the date it was created. By default I want to show the current month's records.
I want to find all records from the current month. Some slips might be generated on 1st of month some on 10th but it should show all rows of the given month.
SELECT DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1)
I'm using this statement to get the records that were stored in table on the first date of this month but what about the records saved on 2nd or 3rd and so on?
Try using where condition
where YEAR(date_column)=YEAR(GETDATE()) and MONTH(date_column)=MONTH(GETDATE())
Another solution-
declare #tbl table (Slipdate datetime)
insert into #tbl (Slipdate)
select '2018-02-01'
union
select '2018-02-23'
union
select '2018-01-01'
select *
from #tbl
where dateadd(month,datediff(month,0,Slipdate),0) = dateadd(month,datediff(month,0,GETDATE()),0)

Problèm with SQL select grouping

I have a small problem with a SQL Server query.
I have an issue with my view of several base tables with duplicate values, so far no problem, these duplicates are logical. By unfortunately I do not get the desired end result, I could do it by programming the front end of my application but I would prefer to do the work on the server.
I will explain the principle:
I have 30 companies which each have an employee table.
My view is a union of the 30 employee tables.
Each employee has a unique serial number, the number is the same across tables, so an employee named "John Doe" with an ID number 'S0000021' can be hired in Company A then transferred to company Q without any problems, it will retain the serial number 'S0000021'.
The difference between the data from the Employee tables A and Q will be in this example the start (hire) and release (transfer) dates entered for Company A and just the start date for company Q so the view will have 2 lines for "John Doe".
12 common fields are the following:
Serial Number (Identical in every employee table)
Social Security Number (Same in every employee table)
Start/Hire Date
Release/Transfer date (empty/null if the employee is current)
Name (Can change across companies if the person divorces)
First name
Maiden name
Last Name
Gender
Final Released
Company Code
The problem seems simple that I would not appear that the latest information of the employee, except with a group by, if it has changed name or release date, it will be displayed twice.
I tried the following different ways but they don't return what I want
I returned results both ways but I always see duplicates because my dates within companies are never identical, and their name may change.
Sorry for this Google translation.
1 --
select
vue.matricule,
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
from
vue
group by
vue.matricule,
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
2---
select
distinct(vue.matricule),
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
from
vue
I assumed the following:
there is a view (vue) that already gathers all data from each of the 30 companies
you are just looking for the latest record for each employee
If you need to also see a record for each name change we can change this.
--set up test data
declare #vue table (
matricule varchar(20),
numsecu varchar(20),
name varchar(20),
lastname varchar(20),
maidenname varchar(20),
secondname varchar(20),
genre varchar(20),
start datetime,
released datetime,
companycode varchar(20));
insert #vue values
('S0000021','123456789','John', 'Doe',null,null,'M','2015-01-01','2015-12-31','A'),
('S0000021','123456789','Johnny', 'Doe',null,null,'M','2016-01-01',null,'Q'), --new company, name change, currently employed
('S0000022','123456780','Jane', 'Doe',null,null,'M','2015-01-01','2015-12-31','A'),
('S0000022','123456780','Jane', 'Doe',null,null,'M','2016-01-01','2016-02-01','Q'); --new company, name change, terminated
select * from #vue order by matricule, start;
--get latest record for each employee
select *
from (--add row numbering
select *, row_number() over (partition by matricule order by start desc) row_num
from #vue
) vue2
where vue2.row_num = 1;

SQL Server how to make a good structured database with different tables

I want to create an application that loads data from a database by selecting month and year: https://gyazo.com/8a08f56231900945d20dc3801993834a
The thing is that I don't know how the structure of the database.
For example: I need to know the salary of an employee of the year January 2010 and February 2015. Do I need to create tables tbl2010January and tbl2015February? That seems to be ultra noob to create 12 different tables for each year.
The problem that I also might have is how do I make a relation of an employee in every table?
For example: does an Employee1 need to have a relation with every table from tbl2010January till tbl2016December?
Can someone please help me out with this problem? I'm not so experienced with programming but am eager to learn!
All you would need is a singular salary table with either (Employee Id, Year, Month) OR (Employee Id, Date)
You'll need to create some indexes on Employee ID and the date or year/month.
This way you can create queries to either sum the entire year and get individual months without the need for separate tables.
CREATE TABLE dbo.Salary
(
fkEmployeeId int,
Salary decimal,
SalaryYear int,
SalaryMonth int
);
CREATE INDEX IX_Salary_Employee_Date ON Salary(fkEmployeeId, SalaryYear, SalaryMonth)
DECLARE #Year int = 2016
DECLARE #Month int = 1
SELECT *
FROM Salary s
INNER JOIN MyEmployeeTable e on e.pkEmployeeId = s.fkEmployeeId
WHERE SalaryYear = #Year and SalaryMonth = #Month

How can I create a table that combines the date for multiple users even if it's null date for that user?

I'm trying to create a table that shows the history of every users purchase history. I have one table that shows the date, #DateTable and another table that shows each individual purchase with columns, "UserNumber" and "PurchaseDate" and "Purchaseamount"
How can I join these two together to get the sum of each users Purchaseamount for every single day, even if they don't make a purchase that day?
Maybe you can accomplish this by using only your second table?
SELECT UserNumber,
PurchaseDate,
(CASE
WHEN PurchaseAmount IS NULL THEN '0'
ELSE SUM(PurchaseAmount)
END) PurchaseAmount
FROM PurchaseTable
GROUP BY UserNumber, DAY(PurchaseDate)
If the above doesn't work, try modifying to WHEN SUM(PurchaseAmount) IS NULL...

Resources