I have a table that has a key and an alternative key column within the same table. If a value is set in the key column, it must not be used in the alternative key column and vice versa. `
For example, this should be valid:
-----------------------------
| Key | alternative Key |
|---------|-----------------|
| Key_1 | NULL |
| Key_2 | NULL |
| Key_3 | Key_36 |
| Key_4 | NULL |
| ... | ... |
-----------------------------
But this should not be allowed:
-----------------------------
| Key | alternative Key |
|---------|-----------------|
| Key_1 | NULL |
| Key_2 | NULL |
| Key_3 | Key_1 |
| Key_4 | NULL |
| ... | ... |
-----------------------------
The root of the problem is, that my system communicates with a PLC through these keys. However, there are some use-cases where the key we send to the PLC is different from the key we display on screen. The key is always displayed on screen, but if an alternative key is present, it is used for communication instead of the key.
Is it possible to prevent this using SQL constraints or do I need to handle this in my business logic? I am using a code-first approach with C# entities using entity framework core, if that makes a difference. I don't want to change my data-model, if I don't have to.
I agree 100% with the above comments about correcting your data model. Some databases, e.g., Sql Server, support unique indexes on schema-bound views. A view like Select Key From TheTable Union All Select AlternateKey From TheTable Where AlternateKey Is Not Null could then enforce a unique constraint.
Related
I am currently developing an entity framework application in .NET and I am struggling with one query that I have to do with T-SQL.
First of all I want to show you my model from the database and know if the model is right in terms of normalization. I want to mention that I am not an expert at SQL Server database design and maybe this would be easy for the experienced but for me it is not.
The objective of the application I am currently developing is to implement an inventory control system with INS and OUTS to be able to know in which events this equipment had been used and when it was taken in and out with the precise date.
For this example I am taking only 6 tables from my database design.
I have 3 base tables and 3 auxiliary tables to relate the base tables.
Equipo:
Id | int | not null | primary key
Marca | nvarchar(max) | not null
Modelo | nvarchar(max) | not null
Evento:
Id | int | not null | primary key
Sede | nvarchar(max) | not null
Salida:
Id | int | not null | primary key
Fecha | datetime2(0) | not null
And the next three tables are the tables that relates the base tables.
EventoEquipo:
EventoId | int | not null | primary key (References Evento.Id)
EquipoId | int | not null | primary key (References Equipo.Id)
SalidaEvento:
SalidaId | int | not null | primary key (References Salida.Id)
EventoId | int | not null | (References Evento.Id)
SalidaEquipo:
SalidaId | int | not null | primary key (References Salida.Id)
EquipoId | int | not null | (References Equipo.Id)
The SQL query that I need to find is a query that allows me to get the Events from an specific Equipment with their out dates and in case there is no out registered then I should get a null in the out date.
I was able to develop this partial query:
DECLARE #EquipoId int
SET #EquipoId = 4
SELECT ev.Nombre
FROM Evento ev
INNER JOIN EventoEquipo eve ON eve.EventoId = ev.Id
INNER JOIN Equipo eq ON eq.Id = eve.EquipoId
WHERE eq.Id = #EquipoId
This query allows me to get the Events in which the Equipment was used but if I proceed with the same logic for the outs I only will get the events that have an out registered and I need to get all the events even if there is no out registered.
Thank you in advance!
PS: Sorry for the basic table visuals but I was unable to upload more than 2 images.
I am struggling with a simple update statement in Oracle. The update itself has not changed in forever but the table has grown massively and the performance is now unacceptable.
Here is the low down:
70 columns
27 indexes (which I am not under any circumstances allowed to reduce)
50M rows
Update statement is just hitting one table.
Update statement:
update TABLE_NAME
set NAME = 'User input string',
NO = NO,
PLANNED_START_DATE = TO_DATE('3/2/2016','dd/mm/yyyy'),
PLANNED_END_DATE = TO_DATE('3/2/2016','dd/mm/yyyy'),
WHERE ID = 999999 /*pk on the table*/
Execution Plan:
==================
Plan hash value: 2165476569
-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 245 | 1 (0)| 00:00:01 |
| 1 | UPDATE | TABLE_NAME | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| TABLE_NAME | 1 | 245 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_INDEX | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=35133238)
==================================================
The update statement originates in a C# application but I am free to change the statement there.
Select statements still perform well thanks to all the indexes but as I see it that is exactly what is wrong with the update - it has to go update all the indexes.
We are licensed for partitioning but this table is NOT partitioned.
How can I improve the performance of this update statement without altering the table or its indexes?
Are you sure that column id is primary key? And is primary key based on unique index? Because in this case CBO would use INDEX UNIQUE SCAN. In your plan CBO expected 188 rows using filter ID (primary kay) = value and uses INDEX RANGE SCAN
I have trouble with fitnesse adding a prefix "set" to names of my methods and therefore not finding any. It does not do the same thing with a different method from same, which I figured is because said method starts with "get" so I guess there is something I am missing in the syntax since this keyword makes it act differently.
Fitnesse code:
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,C:\Users\Kain\Source\repos\mc\build\Tools\fitnesse\fitSharp.dll %p}
!define TEST_RUNNER {C:\Users\Kain\Source\repos\mc\build\Tools\fitnesse\RunnerW.exe}
!define TEST_SYSTEM {slim}
!path ..\..\results\WindowsHost\Acceptance.Tests.dll
!|Namespace.ConnectorClass|
| get connector schemas |
| ensure | has input schema defined |
| ensure | has output schema defined |
!|Namespace.ConnectorClass|
| send valid query |
| ensure | is valid input |
| ensure | is valid response |
| reject | is error response |
| show | error |
Output:
It looks like you are trying to use the Slim script table. So you need to put script in the first cell of your table:
!|script|Namespace.ConnectorClass|
| get connector schemas |
| ensure | has input schema defined |
| ensure | has output schema defined |
See http://fitnesse.org/FitNesse.UserGuide.WritingAcceptanceTests.SliM.ScriptTable
Without the script cell, Slim is treating your table as a Slim decision table.
I need an idea. I have an app, a winform having multiple tabs in it. There are a bunch of people using it, but none of them needs to use all the tabs, just a couple of them. I've reached a point where it's hard to handle from the source code, so I need a solution to easily manage the permissions. The best would be to use an SQL table for this as I also have to provide for another guy the possibility to modify the rights. I think it would be fine to simply remove the tabs by creating an sql table like this, and at the program startup simply query something like this:
select tabid from table where loggedinuser = 0
and then just loop through the result and remove all of them
foreach(tabid in tabids)
{
tabControl1.TabPages.RemoveByKey(tabid);
}
table:
+----------+----------+-------+-------+-------+
| tabid | name | user1 | user2 | user3 |
+----------+----------+-------+-------+-------+
| tabPage1 | project1 | 0 | 1 | 0 |
+----------+----------+-------+-------+-------+
| tabPage2 | project2 | 1 | 0 | 1 |
+----------+----------+-------+-------+-------+
| tabPage3 | project3 | 1 | 0 | 0 |
+----------+----------+-------+-------+-------+
However I somehow feel that this is not an elegant solution, especially because you have create a new column each time a new guy has to be added. Do you have any idea how to solve it?
I think this is an issue of the database's design, and a basic one; perhaps you need to improve your understanding of SQL databases, particularly relationships and primary/foreign keys. You shouldn't add new columns but new rows.
You need a table for the users, one for the tabs and one to connect the two. Such as this:
User:
+---------+------+
| user_id | name |
+---------+------+
| 1 | John |
+---------+------+
| 2 | Jane |
+---------+------+
Tab:
+--------+----------+
| tab_id | title |
+--------+----------+
| 1 | Articles |
+--------+----------+
| 2 | Products |
+--------+----------+
UserTab:
+---------+--------+---------+
| user_id | tab_id | enabled |
+---------+--------+---------+
| 1 | 1 | 1 |
+---------+--------+---------+
| 1 | 2 | 0 |
+---------+--------+---------+
| 2 | 1 | 0 |
+---------+--------+---------+
| 2 | 2 | 1 |
+---------+--------+---------+
In this example, John can only access Articles and Jane can only access Products.
You should get the ID of the current user and get the entries from UserTab, then remove the tabs that correspond to the IDs for which enabled=0.
You also should make a "default" choice for when the right combination of user and tab doesn't exist in the UserTab table: either display the tab by default or hide it by default.
If you do it through SQL, a simple data model could be :
USER TABLE would have fields user_id,username,... all USER related fields you wish
ROLE TABLE would have fields role_id,role_name
USERROLE TABLE would have fields f_user_id,f_role_id(both foreign keys)
Each record (line) in this table links a user to a role, so a user can have many roles, and a role can be attribuated to many users. That's called a many-to-many relationship
ROLERIGHT TABLE would have fields f_role_id,tabid
Each record (line) in this table links a role to a tab that this role has access to. That means if a role should access all tabs and you've got 10 tabs, you'll have 10 lines with the same role_id and a different tabid from 1 to 10. It is also a many-to-many relationship.
This is quite an usual database pattern for access right management I guess. Now what you have to do is define the several roles. And assign it to the different users. If a new user comes in and he should have the same rights as another user, you just have to assign him the same role(s) as the other user. Depending on complexity and the number of possible tabs/users combinations, you will or not have many roles with few rights, or a few roles with access to several tabs. The latter would probably be the case for a limited number of users, but the good thing is that you could easily scale up without changing the model, only the data.
There is a horrible legacy tool at my workplace that has been updated/patched to output information to an SQLite database. No one wants to touch the back end of the system, and I don't know enough to dig into it - not my problem. Here is my problem however:
I have an SQLite database, with a number of tables in it. Each table represents a day and contains all of the bus runs, listed such as such:
| Direction | Time | RunNumber | StopIndex |
----------------------------------------------
| In | 6:30 | 1 | 1 |
| In | 6:35 | 1 | 2 |
| In | 6:40 | 1 | 3 |
| In | 6:45 | 1 | 4 |
| In | 7:30 | 2 | 1 |
| In | 7:35 | 2 | 2 |
| In | 7:40 | 2 | 3 |
| In | 7:45 | 2 | 4 |
| Out | 6:40 | 1 | 1 |
| Out | 6:45 | 1 | 2 |
| Out | 6:50 | 1 | 3 |
| Out | 6:55 | 1 | 4 |
Some days can have more run's than others. The numbers of stops will be the same across all tables.
The definition of equal is that both direction and time are the same. Each run is treated as a set - if one of the times for a stop differs, then the entire run needs to be merged into a table.
My question is:
What would be the easiest way, given a list of tables, to generate another table that contains values that were not present on all the given tables? This can be done on the SQLite side, or by C# .NET 4.0.
In reality, I only need to know the run number that differs, so I can later extract it and put it into an Excel Spreadsheet, if that makes it any easier.
Try using EXCEPT. For example, the following query will list all rows that exist in Table1 but do not exist in Table2:
SELECT Direction, Time, RunNumber, StopIndex
FROM Table1
EXCEPT
SELECT Direction, Time, RunNumber, StopIndex
FROM Table2