sql插入子表和父表
我有两个具有多对一关系的表。 (Oracle)
**Table: PARENT**
Field: A (PK)
Field: B
Field: C1
Field: C2
Field: C3
Field: C4
Field: C5
**Table CHILD**
Field: A (PK) (FK to PARENT.A)
Field: D (PK)
Field: E
插入子表和父表的记录是同时插入的。
我想知道什么是最有效的方法来做到这一点。
当前,有一个存储过程由调用应用程序调用来完成整个插入步骤。该存储过程当前具有以下签名:
Field: A
Field: B
Field: C (dilimited string)
Field: D (dilimited string)
Field: E (dilimited string)
该过程从输入循环遍历 C,并将每个值存储在数组中。然后使用该数组以及输入中的 A 和 B 插入到表 PARENT 中。
然后使用输入中的 A 并循环输入中的 D 和 E,并将分隔字符串中的每个项目插入到表 CHILD 中。
每天最多会调用 300 万次。它需要尽可能高效。
当进行多个 SP 调用而不是一次调用时,效率会损失多少?
处理有限字符串的所有循环看起来工作量很大!
我认为调用应用程序可以为 CHILD 中的每个条目进行单独的 SP 调用。但是,我怎样才能确保在插入到 PARENT 之前不会以某种方式插入到 CHILD 中......这将是更多的存储过程调用。 (很多时候没有要插入的子记录,有的时候一般少于10条,但可能多达50条)
我也开放另一种方式来获取稀释字符串C中的信息。
有没有比这更有效的方法一个 while 循环从分隔字符串中获取信息?
我没有写 SP,我被要求做一个小的修改,并在可能的情况下使其更有效。
有什么想法吗?
注意:
我简化了表格,实际上在重复字符串 C 中有 10 个项目,而不是 5 个,还有两个像 C 一样的重复字符串插入到表 PARENT 中。这些表中的字段也比显示的多几个
。记录将在 30 天后删除。
I have two tables with a many-to-one relationship. (Oracle)
**Table: PARENT**
Field: A (PK)
Field: B
Field: C1
Field: C2
Field: C3
Field: C4
Field: C5
**Table CHILD**
Field: A (PK) (FK to PARENT.A)
Field: D (PK)
Field: E
Records inserted into the child and parent tables are inserted at the same time.
What I am wondering is what is the most efficient way to do this.
Currently there is one stored procedure that is called by the calling application for this whole insert step. The stored procedure currently has the following signiture:
Field: A
Field: B
Field: C (dilimited string)
Field: D (dilimited string)
Field: E (dilimited string)
The procedure loops through C from the input and stores each of the values in an array. Then uses that array along with A and B from the input to insert into table PARENT.
Then the uses A from the input and loops through D and E from the input and makes an insert into table CHILD for each item in the dilimited strings.
This will be called up to 3 million times per day. It needs to be as efficient as possible.
How much efficency is lost when making multiple SP calls rather than just one?
All the looping to take care of the dilimited strings seem like a lot of work!
I was thinking that the calling application could make seperate SP calls for each of the entries into CHILD. However, how can I ensure that somehow the insert into CHILD wont happen before the insert into PARENT... and that would be more stored procedure calls. (many times there is no child records to insert, when there is there is generally less than 10, but could be as many as 50)
I also open to another way to get the information in dilimted string C.
Is there something more efficent than a while loop to get the information from dilimited strings?
I didn't write the SP I was asked to make a small modification and make it more efficent if possible.
Any ideas?
Notes:
I simplified the tables, there are actually 10 items in dilitied string C not 5, there are also two more dilited strings just like C that get inserted into table PARENT. The tables also have several more fields than shown
Records are deleted after 30 days.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里有一些事情......
首先,如果您循环遍历分隔字符串以将相似的项目放入相似的列中,您可能需要重构您的表以使其更加规范化。例如,如果
C
是电话号码分隔列表,并且列C1
-C5
为phone1
- < code>phone5,您可能应该有一个单独的子phone
表。这取决于用例,但让我觉得这是一个潜在的未来问题(即分隔符的知识)。如果分隔字符串中包含不同的数据(电话号码、城市、姓名等) - 请为每个单独的数据元素创建单独的输入参数。这是一个更大的潜在问题(因为如果条目的顺序很重要,那么你就完蛋了)。
你是对的,循环分隔字符串需要大量工作。不一定有更好的方法来做到这一点,除非您的 RDBMS 有某种内置的 split 函数或其他函数(或者您可以调用外部函数)。如果可以的话,我宁愿避免它,并调用
child
存储过程。它必须是针对每个孩子的,但这实际上更好——不一定是性能方面的,而是为了概念化它和未来的维护。如何防止在没有
父
的情况下插入子
行?使用外键约束。如果违反约束,则这是调用者的错,而不是数据库的错。好的,其中一些需要对 SP 进行一些重大更改,有些需要对底层表结构进行更改(如果最初设置正确,则应该对用户来说大部分是透明的)。但这就是我想要尝试的......
哦,皮斯告诉我这一切都在承诺控制下运行......
There are a couple of things here....
First, if you're looping through a delimited string to put similar items in similar columns, you likely need to refactor your tables to be more normalized. For example, if
C
is a delimited list of phone numbers, and columnsC1
-C5
arephone1
-phone5
, you should likely have a separate childphone
table. This is dependant on use case, but strikes me as a potential future problem (ie knowledge of the delimiter).If the delimited string has dis-similar data in it (phone number, city, name, etc) - please make separate entry paramets for each separate data element. This is an even bigger potential problem (because if the order of the entries is important, you're screwed, period).
You're right, looping over delimited strings is a lot of work. There's not necessarily a better way to do it, unless possibly if your RDBMS has some sort of built-in
split
function or something (or you can call an external function). I'd rather avoid it if I could, and call achild
stored procedure. It's going to have to be per-child, but that's actually better anyways - not necessarily performance wise, but for conceptualizing it, and future maintanence.How to prevent a
child
row from being inserted without aparent
? Use a foreign key constraint. If the constraint is violated, it's the caller's fault, and not the DB's.Okay, some of these require some major changes to the SP, and some require changes to the underlying table structure (which, if it was initially set up correctly, should be mostly transparent to the users). But this is what I would have attempted...
Oh, and pease tell me this is all running under commitment control...
处理此问题的最有效方法可能是使用用户定义的数据类型将值列表作为数组而不是分隔字符串传递到存储过程。像这样的事情:
如果包设计得好,将插入包装在包中不会增加大量的执行时间。这包括使用批量插入(如我使用
forall
的地方所示)和使用数据库可以自然读取的数据结构,而不是对数据进行编码和解码(就像您当前对分隔值所做的那样) 。The most efficient way to handle this is likely to use user-defined data types to past the lists of values to the stored procedure as arrays, rather than as delimited strings. Something like this:
Wrapping the inserts in a package won't add significant execution time if the package is designed well. That includes using bulk inserts (as shown where I used
forall
) and using data structures that the database can read naturally, rather than encoding and decoding the data (as you're currently doing with the delimited values).