Dynamic field in SQL Server Express - sql

So I've found myself with a need to have a field in my table that is a count of all the 'Shops' in another table. The table should therefore consist of Centre_Name, Location and Shop_Count. I've already created the table, so how do I add such a field?
The field should also obviously update when a shop is added or deleted in the other table. Also, each shop has a corresponding Centre_Name.
The table is in a SQL Server Express database, linked to my MVC 4 project in Visual Studio.
Thanks!

It's pretty heavy denormalization, but you could make a function to get the count and then use that function as part of a computed column. See: define a computed column reference another table
So you'd want to do:
CREATE FUNCTION dbo.CountShops (#Centre_Name VARCHAR[x])
RETURNS INT
AS BEGIN
DECLARE #ShopCount INT
SELECT #ShopCount = COUNT(*) FROM dbo.Shops WHERE Centre_Name = #Centre_Name
RETURN #ShopCount
END
And then call that as part of your column:
ALTER TABLE dbo.Shops
ADD Shop_Count AS dbo.CountShops(Centre_Name)
...this is assuming Centre_Name is the defining attribute of what you're counting shops by. What are you counting shops by? If it's just counting rows in the shops table, you could drop the parameter and do:
CREATE FUNCTION dbo.CountShops ()
RETURNS INT
AS BEGIN
DECLARE #ShopCount INT
SELECT #ShopCount = COUNT(*) FROM dbo.Shops
RETURN #ShopCount
END
More on computed columns here.

Related

Oracle SQL statement to create temp table with values from stored procedure

I need to create a temp table that is created by looping through a table of numbers and then adding values to the the temp table that pass a stored procedure check.
If this was C# I would write the following:
List<string> tempString = new List<string>;
foreach(var order in OrderList.Orders)
{
if (ShipOrder(order) == true)
tempString.Add(order.OrderId);
}
Or maybe pseudo code would be a better explanation.
Loop through each order in a table of orders. For each order that the stored procedure ShipOrder returns true for add to a temp table of OrdersToShip. Later use the table of OrdersToShip to do an update.
Please note this is a simple version of what I am doing. The procedure to determine if something should be shipped is rather complicated.
Oracle SQL knows no boolean data type, so your function ShipOrder will have to return something else, maybe numbers 1/0 or strings 'Y'/'N', 'TRUE'/'FALSE'. Apart from that, you simply want to select order IDs:
To insert rows into an existing table:
insert into orders_to_ship (orderid)
select orderid
from orders
where shiporder(orderid) = 'TRUE';
Or to create the not yet existing table on-the-fly:
create table orders_to_ship as
select orderid
from orders
where shiporder(orderid) = 'TRUE';
You see you don't need loops in SQL, because you are just describing the data sets you want. And usually you don't need temporary tables either :-)

MS SQL Computed column

I want to create a column based on COUNT(*) on another table, and when a record is deleted from that table it should decrease the value in this new column and vice versa. So, here is the query:
SELECT COUNT (*) FROM dbo.Korisnik1_FakturaStavka GROUP BY dbo.Korisnik1_FakturaStavka.FakturaID
And it returns this:
And when I try to create a computated column like this:
CREATE TABLE test(
NumberOF as (SELECT COUNT (*) FROM dbo.Korisnik1_FakturaStavka GROUP BY dbo.Korisnik1_FakturaStavka.FakturaID) )
I get the following error:
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Here is the main table that I want to compute from:
How can I resolve this ?
You can define a UDF:
create function dbo.NumberOfFakturaID(#id int) returns int as begin
return (select count(1) from Korisnik1_FakturaStavka where id=#id)
end
and then use it as the computed column:
CREATE TABLE test(FakturaID int, NumberOF as dbo.NumberOfFakturaID(FakturaID))
But putting that sort of calc as a computed column should be used with care.
This is too long for a comment.
You can do this by defining a function to calculate the count and using that function in the computed column definition. However, I don't think this is a good idea for frequently used columns, because you will be doing a lot of counting "behind the scenes".
Alternatives:
Set up a view or materialized view with the additional count column.
Do the count explicitly when you need it.
Set up a trigger to store the count in the first table, whenever rows are inserted/updated/deleted from the second table.

Insert multiple parent child records into SQL Server 2008 in a stored procedure

I have two tables Portfolio and Trades. Once the portfolio data has been inserted, using that Id, I insert the trades details into the Trades table.
I will get multiple portfolio in a single request, for example, if I get two portfolio P1 and P2, I need to insert two records into the Portfolio table, and the corresponding trades details into the Trades table once for every portfolio.
How to pass this entire data in a single stored procedure call in order to maintain the transaction?
Starting with sql server 2008, you can use table valued parameters to pass a table structured data in a single call to a stored procedure.
However, Not every client supports this. It's easy to use with .Net, but I doubt it's possible with VBScript, for instance.
In order to use a table valued parameter you must first create a user defined table type:
CREATE TYPE UDT_Portfolio As Table
(
Portfolio_Id int,
Portfolio_Name varchar(10),
.....
)
in your case, since you want to pass 2 tables, you need 2 types:
CREATE TYPE UDT_Trades As Table
(
Trade_Id int,
Trade_Portfolio_Id int,
Trade_Name varchar(10),
....
)
Now, to use them in a stored procedure is very easy:
CREATE PROCEDURE stp_InsertPortfoliosAndTrades
(
#Portfolio UDT_Portfolio readonly, -- Note: Readonly is a must
#Trade UDT_Trades readonly
)
AS
-- stored procedure logic here
Note #1:: Table valued parameters are readonly. meaning you can't use update, insert or delete statements on them.
However, you can declare a table valued variable inside a stored procedure and use insert, update, and deletes on that.
Note #2: If your portfolio id is an identity column, then when inserting the data to the portfolio table you will need to use an output clause to get the new id values.

Can I have a named integral constant for using across stored procedures in T-SQL?

I'd like to have something similar to a C++ integer constant that I could use across different stored T-SQL procedures:
SELECT * FROM SOMETABLE WHERE STATE = IsBeingProcessed;
with IsBeingProcessed being a named integer constant equal to say 4.
Is it possible in T-SQL?
You could create a config table with id, name and value populated with 'BeingProcessed' and 4 and join to the table. Would also foreign key it if possible. This also allows for the status definition to be updated as a table update. i.e. Business decide to change the name from being processed to awaiting processing.
You could create a User Defined Function in the master table which simply does the following:
CREATE FUNCTION dbo.IsBeingProcessed
(
)
RETURNS int
AS
BEGIN
RETURN 4
END
Then this could be called like:
SELECT * FROM SOMETABLE WHERE STATE = dbo.IsBeingProcessed();

MySQL function to compare values in a db table against the previous

Iam quite new to functions in SQL and I would like to create a function to compare values in a MySQL table against previous and I am not sure how to do this.
For example (iId is the input value)
DECLARE pVal INT(20);
DECLARE val INT(20);
SELECT price INTO pVal FROM products WHERE Id=iId;
SELECT price FROM products;
IF price == pVal THEN
SET val = price;
END IF;
Thanks
I was not sure how to run a select query on a table and then return from that function return multiple values once they have been manipulated. Also I was unsure if you could run a SELECT query in a function that returns more than one row. The first answer is that you can not return an array of data or I think more than one row from a function. Therefore I think the best way to do this is to create a temporary table with the new dataset returned.
Example
DROP TEMPORARY TABLE IF EXISTS employeeTemp;
CREATE TEMPORARY TABLE employeeTemp AS
SELECT id,start_date
FROM employee;
Secondly the answer is yes you can run a SELECT query inside a function to return more than one row.
Sorry about this I am quite new to MySQL functions.