I have a simple dimension BP (Business Partner)
The primary key is t_bpid and is "mapped" to the t_BPid attribute.
I have added the Ccty (indicates the City) attribute without problems, dragging it from the Data Source View pane to the Attributes pane.
Then I want to add the description on the BP, so I drag the t_Name from Data Source View to the attributes.
BUT when I try to deploy I get the error:
"Duplicate Attribute Key"
What's the problem?
What's the difference with the t_Ccty attribute?
The t_Name attribute has
KeyColumns set to BP.t_nama (WChar)
NameColumn (none)
(PS. If I change KeyColumns to point to the BP primary key (BP.t_bpid) the error goes away but I don't think this is the correct way to address the problem...)
Seems your dim table in db have that records which one t_bpid mapped to multiple t_nama.
Try this :
select * from(
select t_nama,t_bpid,rownumber()over(partition by t_bpid order by t_nama) as rn
from(
select distinct t_nama,t_bpid from yourtb) a
) b where rn>1
this query will return you the dim records that one t_bpid mapped to multiple t_nama.
If the query return records, then please make sure the key attribute in the dim is mapped to the primary key in db table also.
MDXHelper : IDE to Write, Analyze, Tuning, Debug MDX efficiently
Related
For my project, I implemented linked list with rdbms. The linked list uses rowid column as a pointer, and contains prior, next and owner pointer(from different table).
The simple example would be like this.
CREATE TABLE EMPLOYEE
(
EMP_ID NUMBER(4) NOT NULL,
OFFICE_CODE CHAR(2),
OFF_EMP_prior ROWID,
OFF_EMP_next ROWID,
OFF_EMP_owner ROWID
);
{EMP1,(NULL,EMP2,OFF1)} - {EMP2,(EMP1,EMP3,OFF1)} - {EMP3,(EMP2,NULL,OFF1)}
Now I have to implement a retrieval function like "Find 'nth(integer)' entry of the list which has 'OFF1' as a owner".
This can be simply done by using loop to traverse the linked list. But this requires too many SQL operations for one retrieval. (I know that using sequence number can be another option, but this is the decision made so far.)
Instead, I found SELECT - CONNECTED BY in oracle SQL, and tried
select * from EMPLOYEE
where OFF_EMP_owner = [OFF_ROWID]
connect by nocycle OFF_EMP_prior = rowid;
This query works for retrieving entries of the list, but the order of the result is not as I expected (something like EMP3-EMP1-EMP2).
Is it possible to retrieve entries of the linked list and sort them by the order of the list with SELECT-CONNECT BY'? Or is there exists more suitable SQL?
select * from EMPLOYEE
where DEPT_EMPLOYEE_owner = [OWNER_ROWID}
start with OFF_EMP_prior is NULL
connect by OFF_EMP_prior = prior rowid;
Solved the problem with the query above. 'prior' should be used instead of nocycle.
How can i create a table, that allows only to put data in NAME, if the data matches with the data that i want to be allowed in NAME. So like Bla1 or Bla2.
CREATE TABLE Table1 (
NAME VARCHAR(23)
NAME has to be one of them: ('Bla1', 'Bla2')
)
The best way to do it is probably to have a second table with all the allowed names in it, and making a FOREIGN KEY from the name field in your Table1 to the name field in that other table. That'll automatically fail any insert queries for which the name is not contained in the list of allowed names.
This has an advantage over things like ENUM and such in that it does not require you to rebuild your table (which is a very expensive operation) every time you want to allow another name and it also allows you to later add additional related info to each name by adding it to the other table.
Here's a great article on why using a foreign key is much better than using enums or other such checks in the table itself: http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/
Try this:
CREATE TABLE Table1 (
name VARCHAR(23) CHECK( name IN ('Bla1','Bla2') )
);
We are working on a database to store some evaluations we conduct. There are a few different types of evaluations and some have changed over time. Because of this we need to keep a record of exactly what an evaluation looked like when it was undertaken.
I figured that the best way to support this would be through a template style system.
With:
A table saving all possible options;
A table mapping options to a template;
An evaluations table mapping a participant to a template on a date/time; and
A table mapping evaluator comments to an option of an evaluation.
This is a skeleton for the design:
CREATE TABLE options (
id SERIAL PRIMARY KEY,
option TEXT NOT NULL
);
CREATE TABLE templates (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE template_options (
template INTEGER NOT NULL REFERENCES templates( id ),
option INTEGER NOT NULL REFERENCES options( id ),
UNIQUE ( template, option )
);
CREATE TABLE participants (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE evaluations (
id SERIAL PRIMARY KEY,
template INTEGER NOT NULL REFERENCES templates( id ),
participant INTEGER NOT NULL REFERENCES participants( id ),
date TIMESTAMP WITH TIME ZONE NOT NULL
);
CREATE TABLE evaluation_data (
template INTEGER NOT NULL REFERENCES templates( id ),
option INTEGER NOT NULL REFERENCES options( id ),
evaluator_comments TEXT NOT NULL,
);
The design is able to capture our data but doesn't restrict the options saved in evaluation_data to the subset specified in the evaluation's template's option mapping. We could probably enforce it with a trigger (we can definitely do it with application logic [we are doing so at the moment]) but are we going down the wrong path with this design?
Can anybody think of a better way to do it?
Edit:
Added an example of a potential trigger we would need to use to ensure valid options are enforced with this design.
CREATE FUNCTION valid_option() RETURNS trigger as $valid_option$
BEGIN
IF NOT NEW.option IN ( SELECT template_options.option
FROM template_options
INNER JOIN templates
ON template_options.template = templates.id
WHERE templates.id = ( SELECT evaluations.template
FROM evaluations
WHERE evaluations.id = NEW.evaluation ) ) THEN
RAISE EXCEPTION 'This option is not mapped for this evaluations template.';
END IF;
RETURN NEW;
END
$valid_option$ LANGUAGE plpgsql;
CREATE TRIGGER valid_option BEFORE INSERT ON evaluation_data FOR EACH ROW EXECUTE PROCEDURE valid_option();
Remember that you need two sets of tables. The first set containing the assessment, questions, answer alternatives, categories(?) needed to display the assessment to the participant. The second set of tables to record data about the evaluation (ie. the participant taking the assessment): which assessment, which questions, which answer alternatives and in which order they were presented, which answer they entered (are they allowed to answer the same question multiple times?), etc.
We're using the following structure (I've removed topic scoring since you didn't ask about it):
Models for presenting an assessment:
Assessment: assessment_name, passing_status, version
Question: assessment, question_number, question_type, question_text
AnswerAlternative: question, correct?, answer_text, points
Models for recording an evaluation (participant taking an assessment):
Progress: started_timestamp, finished_timestamp, last_activity, status (includes "finished")
Result: user, assessment, progress, currently_active, score, passing_grade?
Answer: result, question, selected_answer_alternative, answer_text, score
To achieve your goal, I would augment this by writing the generated evaluation to a table and pointing to it from Reault. You could also record the selection and presentation criteria so you can re-generate the assessment programmatically (ie. if you're selecting the questions from a larger question db and re-ordering the answer alternatives before presenting them to the participant).
I'm trying to use set up a database for a school project, and I'm using triggers to set up referential integrity for one table. I have a table, Addresses, which stores the address for People, Studios, and Directors. Then I have a table called Address Reference. This table points to the Address table, and it has a two fields, the ReferenceID and the TableName to show which table and row this address is for. I have a Constraint so TableName will always be valid.
I'm trying to set up a trigger to make sure any rows inserted are valid, which I can do, I'm just trying to improve it. My code would look like this:
SELECT *
FROM inserted
WHERE ReferenceID IN
(SELECT PersonID
FROM inserted.TableName)
However I found I needed to use dynamic sql. So I was thinking something like this:
SELECT *
FROM inserted
WHERE ReferenceID IN
(EXEC('SELECT PersonID FROM' + inserted.TableName))
Which didn't work, even when I removed the exec.
I'm doing this in SQL Server Management Studio With SQL Server 11.0.3128
Let me know if you need any more information. I've looked around, and I haven't found any answers to this question that work.
This is a poor way to maintain referential integrity. There are a number of ways you could approach this.
The first would be to have an address table, then multiple tables to contain the links, e.g.
CREATE TABLE StudioAddress
( StudioID INT NOT NULL,
AddressID INT NOT NULL,
CONSTRAINT PK_StudioAddress__StudioID_AddressID PRIMARY KEY (StudioID, AddressID),
CONSTRAINT FK_StudioAddress__StudioID FOREIGN KEY (StudioID) REFERENCES Studio (StudioID),
CONSTRAINT FK_StudioAddress__AddressID FOREIGN KEY (AddressID) REFERENCES Address (AddressID)
);
This maintains your referenctial integrity without needing triggers, and still caters for a 1 to many relationship.
Another option would be to have 3 nullable columns in your address table (StudioID, PersonID, DirectorID), each with a foreign key to the relevant table, you can the add a check constraint to ensure only one of the 3 fields is populated (if this is required).
I much prefer the first option though, it is much cleaner, and also allows for the same address to be used for multiple things.
ADENDUM
If this has to be done using triggers, then I think you would need to use something like this:
IF EXISTS( SELECT 1
FROM inserted i
WHERE NOT EXISTS
( SELECT 1
FROM People p
WHERE p.PersonID = i.ReferenceID
AND i.TableName = 'People'
UNION ALL
SELECT 1
FROM Studios s
WHERE s.StudioID = i.ReferenceID
AND i.TableName = 'Studios'
UNION ALL
SELECT 1
FROM Directors d
WHERE d.DirectorID = i.ReferenceID
AND i.TableName = 'Directors'
)
)
BEGIN
ROLLBACK TRANSACTION;
RAISERROR('Referential integrity error', 16, 1);
END
This essentially checks that for all inserted/updated rows a record exists with the relevant ID in the relevant table.
I still stand by my earlier answer though, that this is a terrible approach, and I would question any syllabus this is on!
I have the Tables
PatientEligibilit
and
PatientsEligibilitiesDoctorsSpecialties
and
DoctorsSpecialties
PatientEligibilit
has foreign key PatientsEligibilitiesDoctorsSpecialtyID from
PatientsEligibilitiesDoctorsSpecialties
table
and
PatientsEligibilitiesDoctorsSpecialty
has foreign key DoctorsSpecialtyID from
DoctorsSpecialties
table
THEN USING VB.NET LINQ: i'm tring to add child item ( PatientsEligibilitiesDoctorsSpecialty)
to it's parent (PatientEligibilit)
then I submit Changes
like :
PatientEligibilityObject.PatientsEligibilitiesDoctorsSpecialties.Add(New PatientsEligibilitiesDoctorsSpecialty With {.DoctorSpecialtyID = si.ID, .RegDate = Date.Now}) PatientEligibilityObject.PatientsEligibilitiesDoctorsSpecialties.Add(PEDS)
HMSData.SubmitChanges()
it's worked fine and save record in Database with correct date
BUT
DoctorSpecialtyID
always saved with value 1
I solve it. the problem was in the relation between the tables.
The foreign key between PatientEligibilit and PatientsEligibilitiesDoctorsSpecialties
was not correct..