我有一个加载维度,其中description包含一个数据类型为VARCHAR(50).它的排序规则是SQL_Latin1_General_CP1256_CS_AS,它包含阿拉伯语数据,例如"مركزالعقبة".它的源具有相同的类型,大小和排序规则,但每次加载维度时,此字段都会更新!为什么会这样?
在SQL Server 2008+中,我们希望启用对运营数据库中"客户"表的历史更改的跟踪.
这是一个新表,我们的应用程序控制所有写入数据库,所以我们不需要像触发器这样的邪恶黑客.相反,我们会将更改跟踪构建到业务对象层,但我们需要找出要使用的正确数据库模式.
行数将低于100,000,每条记录的变化数量平均为每年1.5.
我们至少有两种方法可以对此进行建模:
作为2型渐变维度称为表CustomersHistory,以列EffectiveStartDate,EffectiveEndDate(设置为NULL为客户的当前版本),以及审计列像ChangeReason和ChangedByUsername.然后我们构建一个Customers过滤到该表的视图EffectiveEndDate=NULL.我们的应用程序的大多数部分将使用该视图进行查询,并且只有需要具有历史记录功能的部分才会查询基础表.为了提高性能,我们可以实现视图和/或在EffectiveEndDate = NULL上添加过滤索引.
使用单独的审计表.对Customer记录的每次更改都会一次写入Customer表并再次写入CustomerHistory审计表.
通过快速回顾StackOverflow问题,#2似乎更受欢迎.但这是因为大多数数据库应用程序必须处理遗留和流氓作家吗?
鉴于我们从一个空白的板岩开始,这两种方法的优点和缺点是什么?你会推荐哪个?
我正在开发一个使用XJC从XSD生成Java POJO的应用程序.有几十种模式,这个数字会增长.应用程序还需要能够处理相同模式的不同版本,这意味着我将有多个模式定义常见类型.我正在尝试自定义绑定,以便某些核心类型实现一个通用接口.JAXB2 Basics的继承插件似乎做了我需要的东西,但我似乎无法确定正确的语法.
这是我的架构的相关部分:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/core"
targetNamespace="http://example.com/core"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
...
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="Address" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
<xs:element name="Province" type="xs:string"/>
<xs:element name="Country" type="xs:string"/>
<xs:element name="County" type="xs:string" minOccurs="0"/>
<xs:element name="PostalCode" type="xs:string"/>
</xs:sequence>
</xs:complexType>
...
</xs:schema>
Run Code Online (Sandbox Code Playgroud)
...这就是我的自定义绑定文件的样子:
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
<jaxb:bindings scd="/type::my:addressType">
<inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements>
<!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Run Code Online (Sandbox Code Playgroud)
我正在使用scd方法,因为在所有显示如何使用inheritence插件的"传统"绑定示例中,指定了schemaLocation.我想避免必须指定schemaLocation,因为我们的模式数量很大(且不断增长).我不想每次添加新架构时都必须更改绑定文件.所以,scd似乎会满足这个要求.
但是当我使用上面的绑定运行构建时,我得到了这个:
Run Code Online (Sandbox Code Playgroud)[xjc] [ERROR] cvc-elt.1: Cannot …
我得到了下表,其中存在以下问题:
从数据集创建缓慢变化的维度类型 2。EMPLOYEE 表记录了每个员工的日常记录。类型 2 - 将具有有效数据和到期日期。
| 员工ID | 日期 | 姓名 | 经理ID |
|---|---|---|---|
| 123 | 3 月 1 日 | 约翰·史密斯 | 1 |
| 123 | 3月2日 | 约翰·史密斯 | 1 |
| 123 | 3月3日 | 约翰·史密斯 | 2 |
| 123 | 3 月 4 日 | 约翰·史密斯 | 3 |
| 123 | 3月5日 | 约翰·史密斯 | 3 |
我相信我的目标表应该如下所示:
| 员工ID | 姓名 | 经理ID | 生效日期 | 截止日期 |
|---|---|---|---|---|
| 123 | 约翰·史密斯 | 1 | 3 月 1 日 | 3月3日 |
| 123 | 约翰·史密斯 | 2 | 3月3日 | 3 月 4 日 |
| 123 | 约翰·史密斯 | 3 | 3 月 4 日 | 无效的 |
我尝试了以下查询:
SELECT employee_id, name, manager_id,
CASE
WHEN LAG(manager_id) OVER() != manager_id THEN e.date …Run Code Online (Sandbox Code Playgroud) 假设我们有一个代表销售办事处的维度.办公室可能会移动,这将是第二类变更.我们希望跟踪旧办公地点发生的操作,以及现在在新办公室发生的操作,并了解发生的变化.到目前为止,只是标准的II型设计.现在让我们说办公室与另一个办公室合并.也就是说,两个最初不同的办事处("母公司")的业务活动现在正在一个办公室("合并办公室")进行,这可能是任何一个办公室的延续(实际或工作人员)原来的办公室,或者它可能是一个新的办公室,从商业的角度来看,是前两个办公室的延续.
报告/分析要求如下:
我不确定如何使用任何SCD类型对此进行建模.如果我们只是用一个新的office条目替换两个父office条目,并相应地更新所有的事实表,我们就会改变一个类型.这让我们看到当前的活动就好了,但我们失去了历史.如果我们将记录分开,我们将不知道合并.如果我们添加第三条记录来代表合并的办公室,我们也会丢失历史记录(它有哪些自然密钥?父办公室的自然密钥都不合适).
我是否需要使用桥接/多对多表?这引入了我想避免的复杂性.但是,如果这是最好的方法,那就这样吧.但是,我仍然不确定如何构建它.事实表可能指向办公室入口,办公室将以多对多的方式分组.报告将基于群体进行,而不是直接在办公室维度进行.
ElectricLlama的问题解答
在实现时间日期时间对时,哪种方法更好?
方法一
_RK FROM_DTTM TO_DTTM
1 01-JAN-2012 00:00:00 31-DEC-2012 23:59:59 ------------> Old record closed out
1 01-JAN-2013 00:00:00 31-DEC-4949 23:59:59 ------------> New active record
Run Code Online (Sandbox Code Playgroud)
与过滤子句一起使用,如下所示:
where FROM_DTTM <= &FILTER_DATE <= TO_DTTM
Run Code Online (Sandbox Code Playgroud)
方法2
_RK FROM_DTTM TO_DTTM
1 01-JAN-2012 00:00:00 01-JAN-2013 00:00:00 ------------> Old record closed out
1 01-JAN-2013 00:00:00 31-DEC-4949 23:59:59 ------------> New active record
Run Code Online (Sandbox Code Playgroud)
与过滤子句一起使用,如下所示:
where FROM_DTTM <= &FILTER_DATE < TO_DTTM
Run Code Online (Sandbox Code Playgroud)
注意事项:
方法 1 与 BETWEEN 子句语法(包含范围)兼容。出于这个原因,我认为这是最好的方法,但是 - 这是我担心的 - 关闭和打开时间戳之间总是存在差距!例如,以下内容(从业务角度来看是错误的)不会返回任何内容:
where FROM_DTTM <= '31-DEC-2012 23:59:59.1'dt <= TO_DTTM
Run Code Online (Sandbox Code Playgroud)
不同的数据库在这里会有不同的精度级别。我想必须有一个标准(过滤时总是四舍五入到最接近的秒),但只是想知道是否还有其他原因支持方法 1(例如建议的双时态“AS …